* target.h: Add to_doc and target_preopen.
[platform/upstream/binutils.git] / gdb / remote-nindy.c
1 /* Memory-access and commands for remote NINDY process, for GDB.
2    Copyright (C) 1990-1991 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 <stdio.h>
99 #include <signal.h>
100 #include <sys/types.h>
101 #include <setjmp.h>
102
103 #include "defs.h"
104 #include "param.h"
105 #include "frame.h"
106 #include "inferior.h"
107 #include "target.h"
108 #include "gdbcore.h"
109 #include "command.h"
110 #include "bfd.h"
111 #include "ieee-float.h"
112
113 #include "wait.h"
114 #include <sys/ioctl.h>
115 #include <sys/file.h>
116 #include <ctype.h>
117 #include "nindy-share/ttycntl.h"
118 #include "nindy-share/demux.h"
119 #include "nindy-share/env.h"
120 #include "nindy-share/stop.h"
121
122 extern int unlink();
123 extern char *getenv();
124 extern char *mktemp();
125
126 extern char *coffstrip();
127 extern void add_syms_addr_command ();
128 extern value call_function_by_hand ();
129 extern void generic_mourn_inferior ();
130
131 extern struct target_ops nindy_ops;
132 extern jmp_buf to_top_level;
133 extern FILE *instream;
134 extern struct ext_format ext_format_i960[];     /* i960-tdep.c */
135
136 extern char ninStopWhy ();
137
138 int nindy_initial_brk;  /* nonzero if want to send an initial BREAK to nindy */
139 int nindy_old_protocol; /* nonzero if want to use old protocol */
140 char *nindy_ttyname;    /* name of tty to talk to nindy on, or null */
141
142 #define DLE     '\020'  /* Character NINDY sends to indicate user program has
143                          * halted.  */
144 #define TRUE    1
145 #define FALSE   0
146
147 int nindy_fd = 0;       /* Descriptor for I/O to NINDY  */
148 static int have_regs = 0;       /* 1 iff regs read since i960 last halted */
149 static int regs_changed = 0;    /* 1 iff regs were modified since last read */
150
151 extern char *exists();
152 static void dcache_flush (), dcache_poke (), dcache_init();
153 static int dcache_fetch ();
154 \f
155 /* FIXME, we can probably use the normal terminal_inferior stuff here.
156    We have to do terminal_inferior and then set up the passthrough
157    settings initially.  Thereafter, terminal_ours and terminal_inferior
158    will automatically swap the settings around for us.  */
159
160 /* Restore TTY to normal operation */
161
162 static TTY_STRUCT orig_tty;     /* TTY attributes before entering passthrough */
163
164 static void
165 restore_tty()
166 {
167         ioctl( 0, TIOCSETN, &orig_tty );
168 }
169
170
171 /* Recover from ^Z or ^C while remote process is running */
172
173 static void (*old_ctrlc)();    /* Signal handlers before entering passthrough */
174
175 #ifdef SIGTSTP
176 static void (*old_ctrlz)();
177 #endif
178
179 static
180 #ifdef USG
181 void
182 #endif
183 cleanup()
184 {
185         restore_tty();
186         signal(SIGINT, old_ctrlc);
187 #ifdef SIGTSTP
188         signal(SIGTSTP, old_ctrlz);
189 #endif
190         error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
191 }
192 \f
193 /* Clean up anything that needs cleaning when losing control.  */
194
195 static char *savename;
196
197 static void
198 nindy_close (quitting)
199      int quitting;
200 {
201   if (nindy_fd)
202     close (nindy_fd);
203   nindy_fd = 0;
204
205   if (savename)
206     free (savename);
207   savename = 0;
208 }
209
210 /* Open a connection to a remote debugger.   
211    FIXME, there should be a way to specify the various options that are
212    now specified with gdb command-line options.  (baud_rate, old_protocol,
213    and initial_brk)  */
214 void
215 nindy_open (name, from_tty)
216     char *name;         /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
217     int from_tty;
218 {
219
220   if (!name)
221     error_no_arg ("serial port device name");
222
223   target_preopen (from_tty);
224   
225   nindy_close (0);
226
227         have_regs = regs_changed = 0;
228         dcache_init();
229
230         /* Allow user to interrupt the following -- we could hang if
231          * there's no NINDY at the other end of the remote tty.
232          */
233         immediate_quit++;
234         nindy_fd = ninConnect( name, baud_rate? baud_rate: "9600",
235                         nindy_initial_brk, !from_tty, nindy_old_protocol );
236         immediate_quit--;
237
238         if ( nindy_fd < 0 ){
239                 nindy_fd = 0;
240                 error( "Can't open tty '%s'", name );
241         }
242
243         savename = savestring (name, strlen (name));
244         push_target (&nindy_ops);
245         target_fetch_registers(-1);
246 }
247
248 /* User-initiated quit of nindy operations.  */
249
250 static void
251 nindy_detach (name, from_tty)
252      char *name;
253      int from_tty;
254 {
255   if (name)
256     error ("Too many arguments");
257   pop_target ();
258 }
259
260 static void
261 nindy_files_info ()
262 {
263   printf("\tAttached to %s at %s bps%s%s.\n", savename,
264          baud_rate? baud_rate: "9600",
265          nindy_old_protocol? " in old protocol": "",
266          nindy_initial_brk? " with initial break": "");
267 }
268 \f
269 /******************************************************************************
270  * remote_load:
271  *      Download an object file to the remote system by invoking the "comm960"
272  *      utility.  We look for "comm960" in $G960BIN, $G960BASE/bin, and
273  *      DEFAULT_BASE/bin/HOST/bin where
274  *              DEFAULT_BASE is defined in env.h, and
275  *              HOST must be defined on the compiler invocation line.
276  ******************************************************************************/
277
278 static void
279 nindy_load( filename, from_tty )
280     char *filename;
281     int from_tty;
282 {
283   char *tmpfile;
284   struct cleanup *old_chain;
285   char *scratch_pathname;
286   int scratch_chan;
287
288   if (!filename)
289     filename = get_exec_file (1);
290
291   filename = tilde_expand (filename);
292   make_cleanup (free, filename);
293
294   scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
295                         &scratch_pathname);
296   if (scratch_chan < 0)
297     perror_with_name (filename);
298   close (scratch_chan);         /* Slightly wasteful FIXME */
299
300   have_regs = regs_changed = 0;
301   mark_breakpoints_out();
302   inferior_pid = 0;
303   dcache_flush();
304
305   tmpfile = coffstrip(scratch_pathname);
306   if ( tmpfile ){
307           old_chain = make_cleanup(unlink,tmpfile);
308           immediate_quit++;
309           ninDownload( tmpfile, !from_tty );
310 /* FIXME, don't we want this merged in here? */
311           immediate_quit--;
312           do_cleanups (old_chain);
313   }
314 }
315
316
317
318 /* Return the number of characters in the buffer before the first DLE character.
319  */
320
321 static
322 int
323 non_dle( buf, n )
324     char *buf;          /* Character buffer; NOT '\0'-terminated */
325     int n;              /* Number of characters in buffer */
326 {
327         int i;
328
329         for ( i = 0; i < n; i++ ){
330                 if ( buf[i] == DLE ){
331                         break;
332                 }
333         }
334         return i;
335 }
336 \f
337 /* Tell the remote machine to resume.  */
338
339 void
340 nindy_resume (step, siggnal)
341      int step, siggnal;
342 {
343         if (siggnal != 0 && siggnal != stop_signal)
344           error ("Can't send signals to remote NINDY targets.");
345
346         dcache_flush();
347         if ( regs_changed ){
348                 nindy_store_registers ();
349                 regs_changed = 0;
350         }
351         have_regs = 0;
352         ninGo( step );
353 }
354
355 /* Wait until the remote machine stops. While waiting, operate in passthrough
356  * mode; i.e., pass everything NINDY sends to stdout, and everything from
357  * stdin to NINDY.
358  *
359  * Return to caller, storing status in 'status' just as `wait' would.
360  */
361
362 void
363 nindy_wait( status )
364     WAITTYPE *status;
365 {
366         DEMUX_DECL;     /* OS-dependent data needed by DEMUX... macros */
367         char buf[500];  /* FIXME, what is "500" here? */
368         int i, n;
369         unsigned char stop_exit;
370         unsigned char stop_code;
371         TTY_STRUCT tty;
372         long ip_value, fp_value, sp_value;      /* Reg values from stop */
373
374
375         WSETEXIT( (*status), 0 );
376
377         /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
378
379         /* Save current tty attributes, set up signals to restore them.
380          */
381         ioctl( 0, TIOCGETP, &orig_tty );
382         old_ctrlc = signal( SIGINT, cleanup );
383 #ifdef SIGTSTP
384         old_ctrlz = signal( SIGTSTP, cleanup );
385 #endif
386
387         /* Pass input from keyboard to NINDY as it arrives.
388          * NINDY will interpret <CR> and perform echo.
389          */
390         tty = orig_tty;
391         TTY_NINDYTERM( tty );
392         ioctl( 0, TIOCSETN, &tty );
393
394         while ( 1 ){
395                 /* Go to sleep until there's something for us on either
396                  * the remote port or stdin.
397                  */
398
399                 DEMUX_WAIT( nindy_fd );
400
401                 /* Pass input through to correct place */
402
403                 n = DEMUX_READ( 0, buf, sizeof(buf) );
404                 if ( n ){                               /* Input on stdin */
405                         write( nindy_fd, buf, n );
406                 }
407
408                 n = DEMUX_READ( nindy_fd, buf, sizeof(buf) );
409                 if ( n ){                               /* Input on remote */
410                         /* Write out any characters in buffer preceding DLE */
411                         i = non_dle( buf, n );
412                         if ( i > 0 ){
413                                 write( 1, buf, i );
414                         }
415
416                         if ( i != n ){
417                                 /* There *was* a DLE in the buffer */
418                                 stop_exit = ninStopWhy( &stop_code,
419                                         &ip_value, &fp_value, &sp_value);
420                                 if ( !stop_exit && (stop_code==STOP_SRQ) ){
421                                         immediate_quit++;
422                                         ninSrq();
423                                         immediate_quit--;
424                                 } else {
425                                         /* Get out of loop */
426                                         supply_register (IP_REGNUM, &ip_value);
427                                         supply_register (FP_REGNUM, &fp_value);
428                                         supply_register (SP_REGNUM, &sp_value);
429                                         break;
430                                 }
431                         }
432                 }
433         }
434
435         signal( SIGINT, old_ctrlc );
436 #ifdef SIGTSTP
437         signal( SIGTSTP, old_ctrlz );
438 #endif
439         restore_tty();
440
441         if ( stop_exit ){                       /* User program exited */
442                 WSETEXIT( (*status), stop_code );
443         } else {                                /* Fault or trace */
444                 switch (stop_code){
445                 case STOP_GDB_BPT:
446                 case TRACE_STEP:
447                         /* Make it look like a VAX trace trap */
448                         stop_code = SIGTRAP;
449                         break;
450                 default:
451                         /* The target is not running Unix, and its
452                            faults/traces do not map nicely into Unix signals.
453                            Make sure they do not get confused with Unix signals
454                            by numbering them with values higher than the highest
455                            legal Unix signal.  code in i960_print_fault(),
456                            called via PRINT_RANDOM_SIGNAL, will interpret the
457                            value.  */
458                         stop_code += NSIG;
459                         break;
460                 }
461                 WSETSTOP( (*status), stop_code );
462         }
463 }
464
465 /* Read the remote registers into the block REGS.  */
466
467 /* This is the block that ninRegsGet and ninRegsPut handles.  */
468 struct nindy_regs {
469   char  local_regs[16 * 4];
470   char  global_regs[16 * 4];
471   char  pcw_acw[2 * 4];
472   char  ip[4];
473   char  tcw[4];
474   char  fp_as_double[4 * 8];
475 };
476
477 static int
478 nindy_fetch_registers(regno)
479      int regno;
480 {
481   struct nindy_regs nindy_regs;
482   int regnum, inv;
483   double dub;
484
485   immediate_quit++;
486   ninRegsGet( (char *) &nindy_regs );
487   immediate_quit--;
488
489   bcopy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
490   bcopy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
491   bcopy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
492   bcopy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
493   bcopy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
494   for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
495     dub = unpack_double (builtin_type_double,
496                          &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
497                          &inv);
498     /* dub now in host byte order */
499     double_to_ieee_extended (ext_format_i960, &dub,
500                              &registers[REGISTER_BYTE (regnum)]);
501   }
502
503   registers_fetched ();
504   return 0;
505 }
506
507 static void
508 nindy_prepare_to_store()
509 {
510   nindy_fetch_registers(-1);
511 }
512
513 static int
514 nindy_store_registers(regno)
515      int regno;
516 {
517   struct nindy_regs nindy_regs;
518   int regnum, inv;
519   double dub;
520
521   bcopy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs,  16*4);
522   bcopy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
523   bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw,     2*4);
524   bcopy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip,           1*4);
525   bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw,         1*4);
526   /* Float regs.  Only works on IEEE_FLOAT hosts.  */
527   for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
528     ieee_extended_to_double (ext_format_i960,
529                              &registers[REGISTER_BYTE (regnum)], &dub);
530     /* dub now in host byte order */
531     /* FIXME-someday, the arguments to unpack_double are backward.
532        It expects a target double and returns a host; we pass the opposite.
533        This mostly works but not quite.  */
534     dub = unpack_double (builtin_type_double, &dub, &inv);
535     /* dub now in target byte order */
536     bcopy ((char *)&dub, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
537         8);
538   }
539
540   immediate_quit++;
541   ninRegsPut( (char *) &nindy_regs );
542   immediate_quit--;
543   return 0;
544 }
545
546 /* Read a word from remote address ADDR and return it.
547  * This goes through the data cache.
548  */
549 int
550 nindy_fetch_word (addr)
551      CORE_ADDR addr;
552 {
553         return dcache_fetch (addr);
554 }
555
556 /* Write a word WORD into remote address ADDR.
557    This goes through the data cache.  */
558
559 void
560 nindy_store_word (addr, word)
561      CORE_ADDR addr;
562      int word;
563 {
564         dcache_poke (addr, word);
565 }
566
567 /* Copy LEN bytes to or from inferior's memory starting at MEMADDR
568    to debugger memory starting at MYADDR.   Copy to inferior if
569    WRITE is nonzero.  Returns the length copied.
570
571    This is stolen almost directly from infptrace.c's child_xfer_memory,
572    which also deals with a word-oriented memory interface.  Sometime,
573    FIXME, rewrite this to not use the word-oriented routines.  */
574
575 int
576 nindy_xfer_inferior_memory(memaddr, myaddr, len, write)
577      CORE_ADDR memaddr;
578      char *myaddr;
579      int len;
580      int write;
581 {
582   register int i;
583   /* Round starting address down to longword boundary.  */
584   register CORE_ADDR addr = memaddr & - sizeof (int);
585   /* Round ending address up; get number of longwords that makes.  */
586   register int count
587     = (((memaddr + len) - addr) + sizeof (int) - 1) / sizeof (int);
588   /* Allocate buffer of that many longwords.  */
589   register int *buffer = (int *) alloca (count * sizeof (int));
590
591   if (write)
592     {
593       /* Fill start and end extra bytes of buffer with existing memory data.  */
594
595       if (addr != memaddr || len < (int)sizeof (int)) {
596         /* Need part of initial word -- fetch it.  */
597         buffer[0] = nindy_fetch_word (addr);
598       }
599
600       if (count > 1)            /* FIXME, avoid if even boundary */
601         {
602           buffer[count - 1]
603             = nindy_fetch_word (addr + (count - 1) * sizeof (int));
604         }
605
606       /* Copy data to be written over corresponding part of buffer */
607
608       bcopy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len);
609
610       /* Write the entire buffer.  */
611
612       for (i = 0; i < count; i++, addr += sizeof (int))
613         {
614           errno = 0;
615           nindy_store_word (addr, buffer[i]);
616           if (errno)
617             return 0;
618         }
619     }
620   else
621     {
622       /* Read all the longwords */
623       for (i = 0; i < count; i++, addr += sizeof (int))
624         {
625           errno = 0;
626           buffer[i] = nindy_fetch_word (addr);
627           if (errno)
628             return 0;
629           QUIT;
630         }
631
632       /* Copy appropriate bytes out of the buffer.  */
633       bcopy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len);
634     }
635   return len;
636 }
637 \f
638 /* The data cache records all the data read from the remote machine
639    since the last time it stopped.
640
641    Each cache block holds 16 bytes of data
642    starting at a multiple-of-16 address.  */
643
644 #define DCACHE_SIZE 64          /* Number of cache blocks */
645
646 struct dcache_block {
647         struct dcache_block *next, *last;
648         unsigned int addr;      /* Address for which data is recorded.  */
649         int data[4];
650 };
651
652 struct dcache_block dcache_free, dcache_valid;
653
654 /* Free all the data cache blocks, thus discarding all cached data.  */ 
655 static
656 void
657 dcache_flush ()
658 {
659   register struct dcache_block *db;
660
661   while ((db = dcache_valid.next) != &dcache_valid)
662     {
663       remque (db);
664       insque (db, &dcache_free);
665     }
666 }
667
668 /*
669  * If addr is present in the dcache, return the address of the block
670  * containing it.
671  */
672 static
673 struct dcache_block *
674 dcache_hit (addr)
675      unsigned int addr;
676 {
677   register struct dcache_block *db;
678
679   if (addr & 3)
680     abort ();
681
682   /* Search all cache blocks for one that is at this address.  */
683   db = dcache_valid.next;
684   while (db != &dcache_valid)
685     {
686       if ((addr & 0xfffffff0) == db->addr)
687         return db;
688       db = db->next;
689     }
690   return NULL;
691 }
692
693 /*  Return the int data at address ADDR in dcache block DC.  */
694 static
695 int
696 dcache_value (db, addr)
697      struct dcache_block *db;
698      unsigned int addr;
699 {
700   if (addr & 3)
701     abort ();
702   return (db->data[(addr>>2)&3]);
703 }
704
705 /* Get a free cache block, put or keep it on the valid list,
706    and return its address.  The caller should store into the block
707    the address and data that it describes, then remque it from the
708    free list and insert it into the valid list.  This procedure
709    prevents errors from creeping in if a ninMemGet is interrupted
710    (which used to put garbage blocks in the valid list...).  */
711 static
712 struct dcache_block *
713 dcache_alloc ()
714 {
715   register struct dcache_block *db;
716
717   if ((db = dcache_free.next) == &dcache_free)
718     {
719       /* If we can't get one from the free list, take last valid and put
720          it on the free list.  */
721       db = dcache_valid.last;
722       remque (db);
723       insque (db, &dcache_free);
724     }
725
726   remque (db);
727   insque (db, &dcache_valid);
728   return (db);
729 }
730
731 /* Return the contents of the word at address ADDR in the remote machine,
732    using the data cache.  */
733 static
734 int
735 dcache_fetch (addr)
736      CORE_ADDR addr;
737 {
738   register struct dcache_block *db;
739
740   db = dcache_hit (addr);
741   if (db == 0)
742     {
743       db = dcache_alloc ();
744       immediate_quit++;
745       ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
746       immediate_quit--;
747       db->addr = addr & ~0xf;
748       remque (db);                      /* Off the free list */
749       insque (db, &dcache_valid);       /* On the valid list */
750     }
751   return (dcache_value (db, addr));
752 }
753
754 /* Write the word at ADDR both in the data cache and in the remote machine.  */
755 static void
756 dcache_poke (addr, data)
757      CORE_ADDR addr;
758      int data;
759 {
760   register struct dcache_block *db;
761
762   /* First make sure the word is IN the cache.  DB is its cache block.  */
763   db = dcache_hit (addr);
764   if (db == 0)
765     {
766       db = dcache_alloc ();
767       immediate_quit++;
768       ninMemGet(addr & ~0xf, (unsigned char *)db->data, 16);
769       immediate_quit--;
770       db->addr = addr & ~0xf;
771       remque (db);                      /* Off the free list */
772       insque (db, &dcache_valid);       /* On the valid list */
773     }
774
775   /* Modify the word in the cache.  */
776   db->data[(addr>>2)&3] = data;
777
778   /* Send the changed word.  */
779   immediate_quit++;
780   ninMemPut(addr, (unsigned char *)&data, 4);
781   immediate_quit--;
782 }
783
784 /* The cache itself. */
785 struct dcache_block the_cache[DCACHE_SIZE];
786
787 /* Initialize the data cache.  */
788 static void
789 dcache_init ()
790 {
791   register i;
792   register struct dcache_block *db;
793
794   db = the_cache;
795   dcache_free.next = dcache_free.last = &dcache_free;
796   dcache_valid.next = dcache_valid.last = &dcache_valid;
797   for (i=0;i<DCACHE_SIZE;i++,db++)
798     insque (db, &dcache_free);
799 }
800
801
802 static void
803 nindy_create_inferior (execfile, args, env)
804      char *execfile;
805      char *args;
806      char **env;
807 {
808   int entry_pt;
809   int pid;
810
811   if (args && *args)
812     error ("Can't pass arguments to remote NINDY process");
813
814   if (execfile == 0 || exec_bfd == 0)
815     error ("No exec file specified");
816
817   entry_pt = (int) bfd_get_start_address (exec_bfd);
818
819   pid = 42;
820
821 #ifdef CREATE_INFERIOR_HOOK
822   CREATE_INFERIOR_HOOK (pid);
823 #endif  
824
825 /* The "process" (board) is already stopped awaiting our commands, and
826    the program is already downloaded.  We just set its PC and go.  */
827
828   inferior_pid = pid;           /* Needed for wait_for_inferior below */
829
830   clear_proceed_status ();
831
832 #if defined (START_INFERIOR_HOOK)
833   START_INFERIOR_HOOK ();
834 #endif
835
836   /* Tell wait_for_inferior that we've started a new process.  */
837   init_wait_for_inferior ();
838
839   /* Set up the "saved terminal modes" of the inferior
840      based on what modes we are starting it with.  */
841   target_terminal_init ();
842
843   /* Install inferior's terminal modes.  */
844   target_terminal_inferior ();
845
846   /* remote_start(args); */
847   /* trap_expected = 0; */
848   /* insert_step_breakpoint ();  FIXME, do we need this?  */
849   proceed ((CORE_ADDR)entry_pt, -1, 0);         /* Let 'er rip... */
850 }
851
852 static void
853 reset_command(args, from_tty)
854      char *args;
855      int from_tty;
856 {
857         if ( !nindy_fd ){
858             error( "No target system to reset -- use 'target nindy' command.");
859         }
860         if ( query("Really reset the target system?",0,0) ){
861                 send_break( nindy_fd );
862                 tty_flush( nindy_fd );
863         }
864 }
865
866 void
867 nindy_kill (args, from_tty)
868      char *args;
869      int from_tty;
870 {
871   return;               /* Ignore attempts to kill target system */
872 }
873
874 /* Clean up when a program exits.
875
876    The program actually lives on in the remote processor's RAM, and may be
877    run again without a download.  Don't leave it full of breakpoint
878    instructions.  */
879
880 void
881 nindy_mourn_inferior ()
882 {
883   remove_breakpoints ();
884   generic_mourn_inferior ();    /* Do all the proper things now */
885 }
886 \f
887 /* This routine is run as a hook, just before the main command loop is
888    entered.  If gdb is configured for the i960, but has not had its
889    nindy target specified yet, this will loop prompting the user to do so.
890
891    Unlike the loop provided by Intel, we actually let the user get out
892    of this with a RETURN.  This is useful when e.g. simply examining
893    an i960 object file on the host system.  */
894
895 nindy_before_main_loop ()
896 {
897   char ttyname[100];
898   char *p, *p2;
899
900   setjmp(to_top_level);
901   while (current_target != &nindy_ops) { /* remote tty not specified yet */
902         if ( instream == stdin ){
903                 printf("\nAttach /dev/ttyNN -- specify NN, or \"quit\" to quit:  ");
904                 fflush( stdout );
905         }
906         fgets( ttyname, sizeof(ttyname)-1, stdin );
907
908         /* Strip leading and trailing whitespace */
909         for ( p = ttyname; isspace(*p); p++ ){
910                 ;
911         }
912         if ( *p == '\0' ){
913                 return;         /* User just hit spaces or return, wants out */
914         }
915         for ( p2= p; !isspace(*p2) && (*p2 != '\0'); p2++ ){
916                 ;
917         }
918         *p2= '\0';
919         if ( !strcmp("quit",p) ){
920                 exit(1);
921         }
922
923         nindy_open( p, 1 );
924
925         /* Now that we have a tty open for talking to the remote machine,
926            download the executable file if one was specified.  */
927         if ( !setjmp(to_top_level) && exec_bfd ) {
928               target_load (bfd_get_filename (exec_bfd), 1);
929         }
930   }
931 }
932 \f
933 /* Define the target subroutine names */
934
935 struct target_ops nindy_ops = {
936         "nindy", "Remote serial target in i960 NINDY-specific protocol",
937         "Use a remote i960 system running NINDY connected by a serial line.\n\
938 Specify the name of the device the serial line is connected to.\n\
939 The speed (baud rate), whether to use the old NINDY protocol,\n\
940 and whether to send a break on startup, are controlled by options\n\
941 specified when you started GDB.",
942         nindy_open, nindy_close,
943         0, nindy_detach, nindy_resume, nindy_wait,
944         nindy_fetch_registers, nindy_store_registers,
945         nindy_prepare_to_store, 0, 0, /* conv_from, conv_to */
946         nindy_xfer_inferior_memory, nindy_files_info,
947         0, 0, /* insert_breakpoint, remove_breakpoint, */
948         0, 0, 0, 0, 0,  /* Terminal crud */
949         nindy_kill,
950         nindy_load, add_syms_addr_command,
951         call_function_by_hand,
952         0, /* lookup_symbol */
953         nindy_create_inferior,
954         nindy_mourn_inferior,
955         process_stratum, 0, /* next */
956         1, 1, 1, 1, 1,  /* all mem, mem, stack, regs, exec */
957         OPS_MAGIC,              /* Always the last thing */
958 };
959
960 void
961 _initialize_nindy ()
962 {
963   add_target (&nindy_ops);
964   add_com ("reset", class_obscure, reset_command,
965            "Send a 'break' to the remote target system.\n\
966 Only useful if the target has been equipped with a circuit\n\
967 to perform a hard reset when a break is detected.");
968 }