HP 300 BSD port for machines at FSF. Also minor mips change.
[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 value call_function_by_hand ();
128 extern void generic_mourn_inferior ();
129
130 extern struct target_ops nindy_ops;
131 extern jmp_buf to_top_level;
132 extern FILE *instream;
133 extern struct ext_format ext_format_i960;       /* i960-tdep.c */
134
135 extern char ninStopWhy ();
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 int nindy_fd = 0;       /* Descriptor for I/O to NINDY  */
147 static int have_regs = 0;       /* 1 iff regs read since i960 last halted */
148 static int regs_changed = 0;    /* 1 iff regs were modified since last read */
149
150 extern char *exists();
151 static void dcache_flush (), dcache_poke (), dcache_init();
152 static int dcache_fetch ();
153 \f
154 /* FIXME, we can probably use the normal terminal_inferior stuff here.
155    We have to do terminal_inferior and then set up the passthrough
156    settings initially.  Thereafter, terminal_ours and terminal_inferior
157    will automatically swap the settings around for us.  */
158
159 /* Restore TTY to normal operation */
160
161 static TTY_STRUCT orig_tty;     /* TTY attributes before entering passthrough */
162
163 static void
164 restore_tty()
165 {
166         ioctl( 0, TIOCSETN, &orig_tty );
167 }
168
169
170 /* Recover from ^Z or ^C while remote process is running */
171
172 static void (*old_ctrlc)();    /* Signal handlers before entering passthrough */
173
174 #ifdef SIGTSTP
175 static void (*old_ctrlz)();
176 #endif
177
178 static
179 #ifdef USG
180 void
181 #endif
182 cleanup()
183 {
184         restore_tty();
185         signal(SIGINT, old_ctrlc);
186 #ifdef SIGTSTP
187         signal(SIGTSTP, old_ctrlz);
188 #endif
189         error("\n\nYou may need to reset the 80960 and/or reload your program.\n");
190 }
191 \f
192 /* Clean up anything that needs cleaning when losing control.  */
193
194 static char *savename;
195
196 static void
197 nindy_close (quitting)
198      int quitting;
199 {
200   if (nindy_fd)
201     close (nindy_fd);
202   nindy_fd = 0;
203
204   if (savename)
205     free (savename);
206   savename = 0;
207 }
208
209 /* Open a connection to a remote debugger.   
210    FIXME, there should be a way to specify the various options that are
211    now specified with gdb command-line options.  (baud_rate, old_protocol,
212    and initial_brk)  */
213 void
214 nindy_open (name, from_tty)
215     char *name;         /* "/dev/ttyXX", "ttyXX", or "XX": tty to be opened */
216     int from_tty;
217 {
218
219   if (!name)
220     error_no_arg ("serial port device name");
221
222   target_preopen (from_tty);
223   
224   nindy_close (0);
225
226         have_regs = regs_changed = 0;
227         dcache_init();
228
229         /* Allow user to interrupt the following -- we could hang if
230          * there's no NINDY at the other end of the remote tty.
231          */
232         immediate_quit++;
233         nindy_fd = ninConnect( name, baud_rate? baud_rate: "9600",
234                         nindy_initial_brk, !from_tty, nindy_old_protocol );
235         immediate_quit--;
236
237         if ( nindy_fd < 0 ){
238                 nindy_fd = 0;
239                 error( "Can't open tty '%s'", name );
240         }
241
242         savename = savestring (name, strlen (name));
243         push_target (&nindy_ops);
244         target_fetch_registers(-1);
245 }
246
247 /* User-initiated quit of nindy operations.  */
248
249 static void
250 nindy_detach (name, from_tty)
251      char *name;
252      int from_tty;
253 {
254   if (name)
255     error ("Too many arguments");
256   pop_target ();
257 }
258
259 static void
260 nindy_files_info ()
261 {
262   printf("\tAttached to %s at %s bps%s%s.\n", savename,
263          baud_rate? baud_rate: "9600",
264          nindy_old_protocol? " in old protocol": "",
265          nindy_initial_brk? " with initial break": "");
266 }
267 \f
268 /******************************************************************************
269  * remote_load:
270  *      Download an object file to the remote system by invoking the "comm960"
271  *      utility.  We look for "comm960" in $G960BIN, $G960BASE/bin, and
272  *      DEFAULT_BASE/bin/HOST/bin where
273  *              DEFAULT_BASE is defined in env.h, and
274  *              HOST must be defined on the compiler invocation line.
275  ******************************************************************************/
276
277 static void
278 nindy_load( filename, from_tty )
279     char *filename;
280     int from_tty;
281 {
282   char *tmpfile;
283   struct cleanup *old_chain;
284   char *scratch_pathname;
285   int scratch_chan;
286
287   if (!filename)
288     filename = get_exec_file (1);
289
290   filename = tilde_expand (filename);
291   make_cleanup (free, filename);
292
293   scratch_chan = openp (getenv ("PATH"), 1, filename, O_RDONLY, 0,
294                         &scratch_pathname);
295   if (scratch_chan < 0)
296     perror_with_name (filename);
297   close (scratch_chan);         /* Slightly wasteful FIXME */
298
299   have_regs = regs_changed = 0;
300   mark_breakpoints_out();
301   inferior_pid = 0;
302   dcache_flush();
303
304   tmpfile = coffstrip(scratch_pathname);
305   if ( tmpfile ){
306           old_chain = make_cleanup(unlink,tmpfile);
307           immediate_quit++;
308           ninDownload( tmpfile, !from_tty );
309 /* FIXME, don't we want this merged in here? */
310           immediate_quit--;
311           do_cleanups (old_chain);
312   }
313 }
314
315
316
317 /* Return the number of characters in the buffer before the first DLE character.
318  */
319
320 static
321 int
322 non_dle( buf, n )
323     char *buf;          /* Character buffer; NOT '\0'-terminated */
324     int n;              /* Number of characters in buffer */
325 {
326         int i;
327
328         for ( i = 0; i < n; i++ ){
329                 if ( buf[i] == DLE ){
330                         break;
331                 }
332         }
333         return i;
334 }
335 \f
336 /* Tell the remote machine to resume.  */
337
338 void
339 nindy_resume (step, siggnal)
340      int step, siggnal;
341 {
342         if (siggnal != 0 && siggnal != stop_signal)
343           error ("Can't send signals to remote NINDY targets.");
344
345         dcache_flush();
346         if ( regs_changed ){
347                 nindy_store_registers ();
348                 regs_changed = 0;
349         }
350         have_regs = 0;
351         ninGo( step );
352 }
353
354 /* Wait until the remote machine stops. While waiting, operate in passthrough
355  * mode; i.e., pass everything NINDY sends to stdout, and everything from
356  * stdin to NINDY.
357  *
358  * Return to caller, storing status in 'status' just as `wait' would.
359  */
360
361 void
362 nindy_wait( status )
363     WAITTYPE *status;
364 {
365         DEMUX_DECL;     /* OS-dependent data needed by DEMUX... macros */
366         char buf[500];  /* FIXME, what is "500" here? */
367         int i, n;
368         unsigned char stop_exit;
369         unsigned char stop_code;
370         TTY_STRUCT tty;
371         long ip_value, fp_value, sp_value;      /* Reg values from stop */
372
373
374         WSETEXIT( (*status), 0 );
375
376         /* OPERATE IN PASSTHROUGH MODE UNTIL NINDY SENDS A DLE CHARACTER */
377
378         /* Save current tty attributes, set up signals to restore them.
379          */
380         ioctl( 0, TIOCGETP, &orig_tty );
381         old_ctrlc = signal( SIGINT, cleanup );
382 #ifdef SIGTSTP
383         old_ctrlz = signal( SIGTSTP, cleanup );
384 #endif
385
386         /* Pass input from keyboard to NINDY as it arrives.
387          * NINDY will interpret <CR> and perform echo.
388          */
389         tty = orig_tty;
390         TTY_NINDYTERM( tty );
391         ioctl( 0, TIOCSETN, &tty );
392
393         while ( 1 ){
394                 /* Go to sleep until there's something for us on either
395                  * the remote port or stdin.
396                  */
397
398                 DEMUX_WAIT( nindy_fd );
399
400                 /* Pass input through to correct place */
401
402                 n = DEMUX_READ( 0, buf, sizeof(buf) );
403                 if ( n ){                               /* Input on stdin */
404                         write( nindy_fd, buf, n );
405                 }
406
407                 n = DEMUX_READ( nindy_fd, buf, sizeof(buf) );
408                 if ( n ){                               /* Input on remote */
409                         /* Write out any characters in buffer preceding DLE */
410                         i = non_dle( buf, n );
411                         if ( i > 0 ){
412                                 write( 1, buf, i );
413                         }
414
415                         if ( i != n ){
416                                 /* There *was* a DLE in the buffer */
417                                 stop_exit = ninStopWhy( &stop_code,
418                                         &ip_value, &fp_value, &sp_value);
419                                 if ( !stop_exit && (stop_code==STOP_SRQ) ){
420                                         immediate_quit++;
421                                         ninSrq();
422                                         immediate_quit--;
423                                 } else {
424                                         /* Get out of loop */
425                                         supply_register (IP_REGNUM, &ip_value);
426                                         supply_register (FP_REGNUM, &fp_value);
427                                         supply_register (SP_REGNUM, &sp_value);
428                                         break;
429                                 }
430                         }
431                 }
432         }
433
434         signal( SIGINT, old_ctrlc );
435 #ifdef SIGTSTP
436         signal( SIGTSTP, old_ctrlz );
437 #endif
438         restore_tty();
439
440         if ( stop_exit ){                       /* User program exited */
441                 WSETEXIT( (*status), stop_code );
442         } else {                                /* Fault or trace */
443                 switch (stop_code){
444                 case STOP_GDB_BPT:
445                 case TRACE_STEP:
446                         /* Make it look like a VAX trace trap */
447                         stop_code = SIGTRAP;
448                         break;
449                 default:
450                         /* The target is not running Unix, and its
451                            faults/traces do not map nicely into Unix signals.
452                            Make sure they do not get confused with Unix signals
453                            by numbering them with values higher than the highest
454                            legal Unix signal.  code in i960_print_fault(),
455                            called via PRINT_RANDOM_SIGNAL, will interpret the
456                            value.  */
457                         stop_code += NSIG;
458                         break;
459                 }
460                 WSETSTOP( (*status), stop_code );
461         }
462 }
463
464 /* Read the remote registers into the block REGS.  */
465
466 /* This is the block that ninRegsGet and ninRegsPut handles.  */
467 struct nindy_regs {
468   char  local_regs[16 * 4];
469   char  global_regs[16 * 4];
470   char  pcw_acw[2 * 4];
471   char  ip[4];
472   char  tcw[4];
473   char  fp_as_double[4 * 8];
474 };
475
476 static int
477 nindy_fetch_registers(regno)
478      int regno;
479 {
480   struct nindy_regs nindy_regs;
481   int regnum, inv;
482   double dub;
483
484   immediate_quit++;
485   ninRegsGet( (char *) &nindy_regs );
486   immediate_quit--;
487
488   bcopy (nindy_regs.local_regs, &registers[REGISTER_BYTE (R0_REGNUM)], 16*4);
489   bcopy (nindy_regs.global_regs, &registers[REGISTER_BYTE (G0_REGNUM)], 16*4);
490   bcopy (nindy_regs.pcw_acw, &registers[REGISTER_BYTE (PCW_REGNUM)], 2*4);
491   bcopy (nindy_regs.ip, &registers[REGISTER_BYTE (IP_REGNUM)], 1*4);
492   bcopy (nindy_regs.tcw, &registers[REGISTER_BYTE (TCW_REGNUM)], 1*4);
493   for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
494     dub = unpack_double (builtin_type_double,
495                          &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
496                          &inv);
497     /* dub now in host byte order */
498     double_to_ieee_extended (&ext_format_i960, &dub,
499                              &registers[REGISTER_BYTE (regnum)]);
500   }
501
502   registers_fetched ();
503   return 0;
504 }
505
506 static void
507 nindy_prepare_to_store()
508 {
509   nindy_fetch_registers(-1);
510 }
511
512 static int
513 nindy_store_registers(regno)
514      int regno;
515 {
516   struct nindy_regs nindy_regs;
517   int regnum, inv;
518   double dub;
519
520   bcopy (&registers[REGISTER_BYTE (R0_REGNUM)], nindy_regs.local_regs,  16*4);
521   bcopy (&registers[REGISTER_BYTE (G0_REGNUM)], nindy_regs.global_regs, 16*4);
522   bcopy (&registers[REGISTER_BYTE (PCW_REGNUM)], nindy_regs.pcw_acw,     2*4);
523   bcopy (&registers[REGISTER_BYTE (IP_REGNUM)], nindy_regs.ip,           1*4);
524   bcopy (&registers[REGISTER_BYTE (TCW_REGNUM)], nindy_regs.tcw,         1*4);
525   /* Float regs.  Only works on IEEE_FLOAT hosts.  */
526   for (regnum = FP0_REGNUM; regnum < FP0_REGNUM + 4; regnum++) {
527     ieee_extended_to_double (&ext_format_i960,
528                              &registers[REGISTER_BYTE (regnum)], &dub);
529     /* dub now in host byte order */
530     /* FIXME-someday, the arguments to unpack_double are backward.
531        It expects a target double and returns a host; we pass the opposite.
532        This mostly works but not quite.  */
533     dub = unpack_double (builtin_type_double, &dub, &inv);
534     /* dub now in target byte order */
535     bcopy ((char *)&dub, &nindy_regs.fp_as_double[8 * (regnum - FP0_REGNUM)],
536         8);
537   }
538
539   immediate_quit++;
540   ninRegsPut( (char *) &nindy_regs );
541   immediate_quit--;
542   return 0;
543 }
544
545 /* Read a word from remote address ADDR and return it.
546  * This goes through the data cache.
547  */
548 int
549 nindy_fetch_word (addr)
550      CORE_ADDR addr;
551 {
552         return dcache_fetch (addr);
553 }
554
555 /* Write a word WORD into remote address ADDR.
556    This goes through the data cache.  */
557
558 void
559 nindy_store_word (addr, word)
560      CORE_ADDR addr;
561      int word;
562 {
563         dcache_poke (addr, word);
564 }
565
566 /* Copy LEN bytes to or from inferior's memory starting at MEMADDR
567    to debugger memory starting at MYADDR.   Copy to inferior if
568    WRITE is nonzero.  Returns the length copied.
569
570    This is stolen almost directly from infptrace.c's child_xfer_memory,
571    which also deals with a word-oriented memory interface.  Sometime,
572    FIXME, rewrite this to not use the word-oriented routines.  */
573
574 int
575 nindy_xfer_inferior_memory(memaddr, myaddr, len, write, target)
576      CORE_ADDR memaddr;
577      char *myaddr;
578      int len;
579      int write;
580      struct target_ops *target;                 /* ignored */
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,
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         0, 0,                   /* Section pointers */
958         OPS_MAGIC,              /* Always the last thing */
959 };
960
961 void
962 _initialize_nindy ()
963 {
964   add_target (&nindy_ops);
965   add_com ("reset", class_obscure, reset_command,
966            "Send a 'break' to the remote target system.\n\
967 Only useful if the target has been equipped with a circuit\n\
968 to perform a hard reset when a break is detected.");
969 }