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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [gdb-5.0/] [gdb/] [nindy-share/] [nindy.c] - Blame information for rev 106

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

Line No. Rev Author Line
1 106 markom
/* This file is part of GDB.
2
 
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; either version 2 of the License, or
6
   (at your option) any later version.
7
 
8
   This program is distributed in the hope that it will be useful,
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
   GNU General Public License for more details.
12
 
13
   You should have received a copy of the GNU General Public License
14
   along with this program; if not, write to the Free Software
15
   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
16
 
17
/* This started out life as code shared between the nindy monitor and
18
   GDB.  For various reasons, this is no longer true.  Eventually, it
19
   probably should be merged into remote-nindy.c.  */
20
 
21
/******************************************************************************
22
 *
23
 *                      NINDY INTERFACE ROUTINES
24
 *
25
 * The caller of these routines should be aware that:
26
 *
27
 * (1) ninConnect() should be called to open communications with the
28
 *     remote NINDY board before any of the other routines are invoked.
29
 *
30
 * (2) almost all interactions are driven by the host: nindy sends information
31
 *     in response to host commands.
32
 *
33
 * (3) the lone exception to (2) is the single character DLE (^P, 0x10).
34
 *     Receipt of a DLE from NINDY indicates that the application program
35
 *     running under NINDY has stopped execution and that NINDY is now
36
 *     available to talk to the host (all other communication received after
37
 *     the application has been started should be presumed to come from the
38
 *     application and should be passed on by the host to stdout).
39
 *
40
 * (4) the reason the application program stopped can be determined with the
41
 *     ninStopWhy() function.  There are three classes of stop reasons:
42
 *
43
 *      (a) the application has terminated execution.
44
 *          The host should take appropriate action.
45
 *
46
 *      (b) the application had a fault or trace event.
47
 *          The host should take appropriate action.
48
 *
49
 *      (c) the application wishes to make a service request (srq) of the host;
50
 *          e.g., to open/close a file, read/write a file, etc.  The ninSrq()
51
 *          function should be called to determine the nature of the request
52
 *          and process it.
53
 */
54
 
55
#include <stdio.h>
56
#include "defs.h"
57
#include "serial.h"
58
#ifdef ANSI_PROTOTYPES
59
#include <stdarg.h>
60
#else
61
#include <varargs.h>
62
#endif
63
 
64
#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY)
65
#define HAVE_SGTTY
66
#endif
67
 
68
#ifdef HAVE_SGTTY
69
#include <sys/ioctl.h>
70
#endif
71
 
72
#include <sys/types.h>  /* Needed by file.h on Sys V */
73
#include <sys/file.h>
74
#include <signal.h>
75
#include <sys/stat.h>
76
 
77
#if 0
78
#include "ttycntl.h"
79
#endif
80
#include "block_io.h"
81
#include "gdb_wait.h"
82
#include "env.h"
83
 
84
#define DLE     0x10    /* ^P */
85
#define XON     0x11    /* ^Q */
86
#define XOFF    0x13    /* ^S */
87
#define ESC     0x1b
88
 
89
#define TIMEOUT         -1
90
 
91
int quiet = 0;   /* 1 => stifle unnecessary messages */
92
serial_t nindy_serial;
93
 
94
static int old_nindy = 0; /* 1 => use old (hex) communication protocol */
95
static ninStrGet();
96
 
97
                /****************************
98
                 *                          *
99
                 *  MISCELLANEOUS UTILTIES  *
100
                 *                          *
101
                 ****************************/
102
 
103
/******************************************************************************
104
 * say:
105
 *      This is a printf that takes at most two arguments (in addition to the
106
 *      format string) and that outputs nothing if verbose output has been
107
 *      suppressed.
108
 *****************************************************************************/
109
 
110
/* VARARGS */
111
static void
112
#ifdef ANSI_PROTOTYPES
113
say (char *fmt, ...)
114
#else
115
say (va_alist)
116
     va_dcl
117
#endif
118
{
119
  va_list args;
120
#ifdef ANSI_PROTOTYPES
121
  va_start(args, fmt);
122
#else
123
  char *fmt;
124
 
125
  va_start (args);
126
  fmt = va_arg (args, char *);
127
#endif
128
 
129
  if (!quiet)
130
    {
131
      vfprintf_unfiltered (gdb_stdout, fmt, args);
132
      gdb_flush (gdb_stdout);
133
    }
134
  va_end (args);
135
}
136
 
137
/******************************************************************************
138
 * exists:
139
 *      Creates a full pathname by concatenating up to three name components
140
 *      onto a specified base name; optionally looks up the base name as a
141
 *      runtime environment variable;  and checks to see if the file or
142
 *      directory specified by the pathname actually exists.
143
 *
144
 *      Returns:  the full pathname if it exists, NULL otherwise.
145
 *              (returned pathname is in malloc'd memory and must be freed
146
 *              by caller).
147
 *****************************************************************************/
148
static char *
149
exists( base, c1, c2, c3, env )
150
    char *base;         /* Base directory of path */
151
    char *c1, *c2, *c3; /* Components (subdirectories and/or file name) to be
152
                         *      appended onto the base directory name.  One or
153
                         *      more may be omitted by passing NULL pointers.
154
                         */
155
    int env;            /* If 1, '*base' is the name of an environment variable
156
                         *      to be examined for the base directory name;
157
                         *      otherwise, '*base' is the actual name of the
158
                         *      base directory.
159
                         */
160
{
161
        struct stat buf;/* For call to 'stat' -- never examined */
162
        char *path;     /* Pointer to full pathname (malloc'd memory) */
163
        int len;        /* Length of full pathname (incl. terminator) */
164
        extern char *getenv();
165
 
166
 
167
        if ( env ){
168
                base = getenv( base );
169
                if ( base == NULL ){
170
                        return NULL;
171
                }
172
        }
173
 
174
        len = strlen(base) + 4;
175
                        /* +4 for terminator and "/" before each component */
176
        if ( c1 != NULL ){
177
                len += strlen(c1);
178
        }
179
        if ( c2 != NULL ){
180
                len += strlen(c2);
181
        }
182
        if ( c3 != NULL ){
183
                len += strlen(c3);
184
        }
185
 
186
        path = xmalloc (len);
187
 
188
        strcpy( path, base );
189
        if ( c1 != NULL ){
190
                strcat( path, "/" );
191
                strcat( path, c1 );
192
                if ( c2 != NULL ){
193
                        strcat( path, "/" );
194
                        strcat( path, c2 );
195
                        if ( c3 != NULL ){
196
                                strcat( path, "/" );
197
                                strcat( path, c3 );
198
                        }
199
                }
200
        }
201
 
202
        if ( stat(path,&buf) != 0 ){
203
                free( path );
204
                path = NULL;
205
        }
206
        return path;
207
}
208
 
209
                /*****************************
210
                 *                           *
211
                 *  LOW-LEVEL COMMUNICATION  *
212
                 *                           *
213
                 *****************************/
214
 
215
/* Read *exactly* N characters from the NINDY tty, and put them in
216
   *BUF.  Translate escape sequences into single characters, counting
217
   each such sequence as 1 character.
218
 
219
   An escape sequence consists of ESC and a following character.  The
220
   ESC is discarded and the other character gets bit 0x40 cleared --
221
   thus ESC P == ^P, ESC S == ^S, ESC [ == ESC, etc.
222
 
223
   Return 1 if successful, 0 if more than TIMEOUT seconds pass without
224
   any input.  */
225
 
226
static int
227
rdnin (buf,n,timeout)
228
    unsigned char * buf;        /* Where to place characters read       */
229
    int n;                      /* Number of characters to read         */
230
    int timeout;                /* Timeout, in seconds                  */
231
{
232
  int escape_seen;      /* 1 => last character of a read was an ESC */
233
  int c;
234
 
235
  escape_seen = 0;
236
  while (n)
237
    {
238
      c = SERIAL_READCHAR (nindy_serial, timeout);
239
      switch (c)
240
        {
241
        case SERIAL_ERROR:
242
        case SERIAL_TIMEOUT:
243
        case SERIAL_EOF:
244
          return 0;
245
 
246
        case ESC:
247
          escape_seen = 1;
248
          break;
249
 
250
        default:
251
          if (escape_seen)
252
            {
253
              escape_seen = 0;
254
              c &= ~0x40;
255
            }
256
          *buf++ = c;
257
          --n;
258
          break;
259
        }
260
    }
261
  return 1;
262
}
263
 
264
 
265
/******************************************************************************
266
 * getpkt:
267
 *      Read a packet from a remote NINDY, with error checking, into the
268
 *      indicated buffer.
269
 *
270
 *      Return packet status byte on success, TIMEOUT on failure.
271
 ******************************************************************************/
272
static
273
int
274
getpkt(buf)
275
     unsigned char *buf;
276
{
277
        int i;
278
        unsigned char hdr[3];   /* Packet header:
279
                                 *      hdr[0] = low byte of message length
280
                                 *      hdr[1] = high byte of message length
281
                                 *      hdr[2] = message status
282
                                 */
283
        int cnt;                /* Message length (status byte + data)  */
284
        unsigned char cs_calc;  /* Checksum calculated                  */
285
        unsigned char cs_recv;  /* Checksum received                    */
286
        static char errfmt[] =
287
                        "Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n";
288
 
289
        while (1){
290
                if ( !rdnin(hdr,3,5) ){
291
                        return TIMEOUT;
292
                }
293
                cnt = (hdr[1]<<8) + hdr[0] - 1;
294
                                        /* -1 for status byte (already read) */
295
 
296
                /* Caller's buffer may only be big enough for message body,
297
                 * without status byte and checksum, so make sure to read
298
                 * checksum into a separate buffer.
299
                 */
300
                if ( !rdnin(buf,cnt,5) || !rdnin(&cs_recv,1,5) ){
301
                        return TIMEOUT;
302
                }
303
 
304
                /* Calculate checksum
305
                 */
306
                cs_calc = hdr[0] + hdr[1] + hdr[2];
307
                for ( i = 0; i < cnt; i++ ){
308
                        cs_calc += buf[i];
309
                }
310
                if ( cs_calc == cs_recv ){
311
                        SERIAL_WRITE (nindy_serial, "+", 1);
312
                        return hdr[2];
313
                }
314
 
315
                /* Bad checksum: report, send NAK, and re-receive
316
                 */
317
                fprintf(stderr, errfmt, cs_recv, cs_calc );
318
                SERIAL_WRITE (nindy_serial, "-", 1);
319
        }
320
}
321
 
322
 
323
/******************************************************************************
324
 * putpkt:
325
 *      Send a packet to NINDY, checksumming it and converting special
326
 *      characters to escape sequences.
327
 ******************************************************************************/
328
 
329
/* This macro puts the character 'c' into the buffer pointed at by 'p',
330
 * and increments the pointer.  If 'c' is one of the 4 special characters
331
 * in the transmission protocol, it is converted into a 2-character
332
 * escape sequence.
333
 */
334
#define PUTBUF(c,p)                                             \
335
        if ( c == DLE || c == ESC || c == XON || c == XOFF ){   \
336
                *p++ = ESC;                                     \
337
                *p++ = c | 0x40;                                \
338
        } else {                                                \
339
                *p++ = c;                                       \
340
        }
341
 
342
static
343
putpkt( msg, len )
344
    unsigned char *msg; /* Command to be sent, without lead ^P (\020) or checksum */
345
    int len;    /* Number of bytes in message                   */
346
{
347
        static char *buf = NULL;/* Local buffer -- build packet here    */
348
        static int maxbuf = 0;   /* Current length of buffer             */
349
        unsigned char ack;      /* Response received from NINDY         */
350
        unsigned char checksum; /* Packet checksum                      */
351
        char *p;                /* Pointer into buffer                  */
352
        int lenhi, lenlo;       /* High and low bytes of message length */
353
        int i;
354
 
355
 
356
        /* Make sure local buffer is big enough.  Must include space for
357
         * packet length, message body, and checksum.  And in the worst
358
         * case, each character would expand into a 2-character escape
359
         * sequence.
360
         */
361
        if ( maxbuf < ((2*len)+10) ){
362
                if ( buf ){
363
                        free( buf );
364
                }
365
                buf = xmalloc( maxbuf=((2*len)+10) );
366
        }
367
 
368
        /* Attention, NINDY!
369
         */
370
        SERIAL_WRITE (nindy_serial, "\020", 1);
371
 
372
 
373
        lenlo = len & 0xff;
374
        lenhi = (len>>8) & 0xff;
375
        checksum = lenlo + lenhi;
376
        p = buf;
377
 
378
        PUTBUF( lenlo, p );
379
        PUTBUF( lenhi, p );
380
 
381
        for ( i=0; i<len; i++ ){
382
                PUTBUF( msg[i], p );
383
                checksum += msg[i];
384
        }
385
 
386
        PUTBUF( checksum, p );
387
 
388
        /* Send checksummed message over and over until we get a positive ack
389
         */
390
        SERIAL_WRITE (nindy_serial, buf, p - buf);
391
        while (1){
392
                if ( !rdnin(&ack,1,5) ){
393
                        /* timed out */
394
                        fprintf(stderr,"ACK timed out; resending\r\n");
395
                        /* Attention, NINDY! */
396
                        SERIAL_WRITE (nindy_serial, "\020", 1);
397
                        SERIAL_WRITE (nindy_serial, buf, p - buf);
398
                } else if ( ack == '+' ){
399
                        return;
400
                } else if ( ack == '-' ){
401
                        fprintf( stderr, "Remote NAK; resending\r\n" );
402
                        SERIAL_WRITE (nindy_serial, buf, p - buf);
403
                } else {
404
                        fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack );
405
                }
406
        }
407
}
408
 
409
 
410
 
411
/******************************************************************************
412
 * send:
413
 *      Send a message to a remote NINDY.  Check message status byte
414
 *      for error responses.  If no error, return NINDY reponse (if any).
415
 ******************************************************************************/
416
static
417
send( out, len, in )
418
    unsigned char *out; /* Message to be sent to NINDY                  */
419
    int len;            /* Number of meaningful bytes in out buffer     */
420
    unsigned char *in;  /* Where to put response received from NINDY    */
421
{
422
        char *fmt;
423
        int status;
424
        static char *errmsg[] = {
425
                "",                                             /* 0 */
426
                "Buffer overflow",                              /* 1 */
427
                "Unknown command",                              /* 2 */
428
                "Wrong amount of data to load register(s)",     /* 3 */
429
                "Missing command argument(s)",                  /* 4 */
430
                "Odd number of digits sent to load memory",     /* 5 */
431
                "Unknown register name",                        /* 6 */
432
                "No such memory segment",                       /* 7 */
433
                "No breakpoint available",                      /* 8 */
434
                "Can't set requested baud rate",                /* 9 */
435
        };
436
#       define NUMERRS  ( sizeof(errmsg) / sizeof(errmsg[0]) )
437
 
438
        static char err1[] = "Unknown error response from NINDY: #%d\r\n";
439
        static char err2[] = "Error response #%d from NINDY: %s\r\n";
440
 
441
        while (1){
442
                putpkt(out,len);
443
                status = getpkt(in);
444
                if ( status == TIMEOUT ){
445
                        fprintf( stderr, "Response timed out; resending\r\n" );
446
                } else {
447
                        break;
448
                }
449
        }
450
 
451
        if ( status ){
452
                fmt =  status > NUMERRS ? err1 : err2;
453
                fprintf( stderr, fmt, status, errmsg[status] );
454
                abort();
455
        }
456
}
457
 
458
                /************************
459
                 *                      *
460
                 *  BAUD RATE ROUTINES  *
461
                 *                      *
462
                 ************************/
463
 
464
/* Table of baudrates known to be acceptable to NINDY.  Each baud rate
465
 * appears both as character string and as a Unix baud rate constant.
466
 */
467
struct baudrate {
468
        char *string;
469
        int rate;
470
};
471
 
472
static struct baudrate baudtab[] = {
473
         "1200", 1200,
474
         "2400", 2400,
475
         "4800", 4800,
476
         "9600", 9600,
477
        "19200", 19200,
478
        "38400", 38400,
479
        NULL,    0               /* End of table */
480
};
481
 
482
/******************************************************************************
483
 * parse_baudrate:
484
 *      Look up the passed baud rate in the baudrate table.  If found, change
485
 *      our internal record of the current baud rate, but don't do anything
486
 *      about the tty just now.
487
 *
488
 *      Return pointer to baudrate structure on success, NULL on failure.
489
 ******************************************************************************/
490
static
491
struct baudrate *
492
parse_baudrate(s)
493
    char *s;    /* Desired baud rate, as an ASCII (decimal) string */
494
{
495
        int i;
496
 
497
        for ( i=0; baudtab[i].string != NULL; i++ ){
498
                if ( !strcmp(baudtab[i].string,s) ){
499
                        return &baudtab[i];
500
                }
501
        }
502
        return NULL;
503
}
504
 
505
/******************************************************************************
506
 * try_baudrate:
507
 *      Try speaking to NINDY via the specified file descriptor at the
508
 *      specified baudrate.  Assume success if we can send an empty command
509
 *      with a bogus checksum and receive a NAK (response of '-') back within
510
 *      one second.
511
 *
512
 *      Return 1 on success, 0 on failure.
513
 ***************************************************************************/
514
 
515
static int
516
try_baudrate (serial, brp)
517
     serial_t serial;
518
     struct baudrate *brp;
519
{
520
  unsigned char c;
521
 
522
  /* Set specified baud rate and flush all pending input */
523
  SERIAL_SETBAUDRATE (serial, brp->rate);
524
  tty_flush (serial);
525
 
526
  /* Send empty command with bad checksum, hope for NAK ('-') response */
527
  SERIAL_WRITE (serial, "\020\0\0\001", 4);
528
 
529
  /* Anything but a quick '-', including error, eof, or timeout, means that
530
     this baudrate doesn't work.  */
531
  return SERIAL_READCHAR (serial, 1) == '-';
532
}
533
 
534
/******************************************************************************
535
 * autobaud:
536
 *      Get NINDY talking over the specified file descriptor at the specified
537
 *      baud rate.  First see if NINDY's already talking at 'baudrate'.  If
538
 *      not, run through all the legal baudrates in 'baudtab' until one works,
539
 *      and then tell NINDY to talk at 'baudrate' instead.
540
 ******************************************************************************/
541
static
542
autobaud( serial, brp )
543
     serial_t serial;
544
     struct baudrate *brp;
545
{
546
  int i;
547
  int failures;
548
 
549
  say("NINDY at wrong baud rate? Trying to autobaud...\n");
550
  failures = i = 0;
551
  while (1)
552
    {
553
      say( "\r%s...   ", baudtab[i].string );
554
      if (try_baudrate(serial, &baudtab[i]))
555
        {
556
          break;
557
        }
558
      if (baudtab[++i].string == NULL)
559
        {
560
          /* End of table -- wraparound */
561
          i = 0;
562
          if ( failures++ )
563
            {
564
              say("\nAutobaud failed again.  Giving up.\n");
565
              exit(1);
566
            }
567
          else
568
            {
569
              say("\nAutobaud failed. Trying again...\n");
570
            }
571
        }
572
    }
573
 
574
  /* Found NINDY's current baud rate; now change it.  */
575
  say("Changing NINDY baudrate to %s\n", brp->string);
576
  ninBaud (brp->string);
577
 
578
  /* Change our baud rate back to rate to which we just set NINDY.  */
579
  SERIAL_SETBAUDRATE (serial, brp->rate);
580
}
581
 
582
                /**********************************
583
                 *                                *
584
                 *   NINDY INTERFACE ROUTINES     *
585
                 *                                *
586
                 * ninConnect *MUST* be the first *
587
                 * one of these routines called.  *
588
                 **********************************/
589
 
590
 
591
/******************************************************************************
592
 * ninBaud:
593
 *      Ask NINDY to change the baud rate on its serial port.
594
 *      Assumes we know the baud rate at which NINDY's currently talking.
595
 ******************************************************************************/
596
ninBaud( baudrate )
597
    char *baudrate;     /* Desired baud rate, as a string of ASCII decimal
598
                         * digits.
599
                         */
600
{
601
  unsigned char msg[100];
602
 
603
  tty_flush (nindy_serial);
604
 
605
  if (old_nindy)
606
    {
607
      char *p;          /* Pointer into buffer  */
608
      unsigned char csum;       /* Calculated checksum  */
609
 
610
      /* Can't use putpkt() because after the baudrate change NINDY's
611
         ack/nak will look like gibberish.  */
612
 
613
      for (p=baudrate, csum=020+'z'; *p; p++)
614
        {
615
          csum += *p;
616
        }
617
      sprintf (msg, "\020z%s#%02x", baudrate, csum);
618
      SERIAL_WRITE (nindy_serial, msg, strlen (msg));
619
    }
620
  else
621
    {
622
      /* Can't use "send" because NINDY reply will be unreadable after
623
         baud rate change.  */
624
      sprintf( msg, "z%s", baudrate );
625
      putpkt( msg, strlen(msg)+1 );     /* "+1" to send terminator too */
626
    }
627
}
628
 
629
/******************************************************************************
630
 * ninBptDel:
631
 *      Ask NINDY to delete the specified type of *hardware* breakpoint at
632
 *      the specified address.  If the 'addr' is -1, all breakpoints of
633
 *      the specified type are deleted.
634
 ***************************************************************************/
635
ninBptDel( addr, type )
636
    long addr;  /* Address in 960 memory        */
637
    char type;  /* 'd' => data bkpt, 'i' => instruction breakpoint */
638
{
639
        unsigned char buf[10];
640
 
641
        if ( old_nindy ){
642
                OninBptDel( addr, type == 'd' ? 1 : 0 );
643
                return;
644
        }
645
 
646
        buf[0] = 'b';
647
        buf[1] = type;
648
 
649
        if ( addr == -1 ){
650
                send( buf, 2, NULL );
651
        } else {
652
                store_unsigned_integer (&buf[2], 4, addr);
653
                send( buf, 6, NULL );
654
        }
655
}
656
 
657
 
658
/******************************************************************************
659
 * ninBptSet:
660
 *      Ask NINDY to set the specified type of *hardware* breakpoint at
661
 *      the specified address.
662
 ******************************************************************************/
663
ninBptSet( addr, type )
664
    long addr;  /* Address in 960 memory        */
665
    char type;  /* 'd' => data bkpt, 'i' => instruction breakpoint */
666
{
667
        unsigned char buf[10];
668
 
669
        if ( old_nindy ){
670
                OninBptSet( addr, type == 'd' ? 1 : 0 );
671
                return;
672
        }
673
 
674
 
675
        buf[0] = 'B';
676
        buf[1] = type;
677
        store_unsigned_integer (&buf[2], 4, addr);
678
        send( buf, 6, NULL );
679
}
680
 
681
 
682
/******************************************************************************
683
 * ninConnect:
684
 *      Open the specified tty.  Get communications working at the specified
685
 *      baud rate.  Flush any pending I/O on the tty.
686
 *
687
 *      Return the file descriptor, or -1 on failure.
688
 ******************************************************************************/
689
int
690
ninConnect( name, baudrate, brk, silent, old_protocol )
691
    char *name;         /* "/dev/ttyXX" to be opened                    */
692
    char *baudrate;/* baud rate: a string of ascii decimal digits (eg,"9600")*/
693
    int brk;            /* 1 => send break to tty first thing after opening it*/
694
    int silent;         /* 1 => stifle unnecessary messages when talking to
695
                         *      this tty.
696
                         */
697
    int old_protocol;
698
{
699
        int i;
700
        char *p;
701
        struct baudrate *brp;
702
 
703
        /* We will try each of the following paths when trying to open the tty
704
         */
705
        static char *prefix[] = { "", "/dev/", "/dev/tty", NULL };
706
 
707
        if ( old_protocol ){
708
                old_nindy = 1;
709
        }
710
 
711
        quiet = silent;         /* Make global to this file */
712
 
713
        for ( i=0; prefix[i] != NULL; i++ ){
714
                p = xmalloc(strlen(prefix[i]) + strlen(name) + 1 );
715
                strcpy( p, prefix[i] );
716
                strcat( p, name );
717
                nindy_serial = SERIAL_OPEN (p);
718
                if (nindy_serial != NULL) {
719
#ifdef TIOCEXCL
720
                        /* Exclusive use mode (hp9000 does not support it) */
721
                        ioctl(nindy_serial->fd,TIOCEXCL,NULL);
722
#endif
723
                        SERIAL_RAW (nindy_serial);
724
 
725
                        if (brk)
726
                          {
727
                            SERIAL_SEND_BREAK (nindy_serial);
728
                          }
729
 
730
                        brp = parse_baudrate( baudrate );
731
                        if ( brp == NULL ){
732
                                say("Illegal baudrate %s ignored; using 9600\n",
733
                                                                baudrate);
734
                                brp = parse_baudrate( "9600" );
735
                        }
736
 
737
                        if ( !try_baudrate(nindy_serial, brp) ){
738
                                autobaud(nindy_serial, brp);
739
                        }
740
                        tty_flush (nindy_serial);
741
                        say( "Connected to %s\n", p );
742
                        free(p);
743
                        break;
744
                }
745
                free(p);
746
        }
747
        return 0;
748
}
749
 
750
#if 0
751
 
752
/* Currently unused; shouldn't we be doing this on target_kill and
753
perhaps target_mourn?  FIXME.  */
754
 
755
/******************************************************************************
756
 * ninGdbExit:
757
 *      Ask NINDY to leave GDB mode and print a NINDY prompt.
758
 ****************************************************************************/
759
ninGdbExit()
760
{
761
        if ( old_nindy ){
762
                OninGdbExit();
763
                return;
764
        }
765
        putpkt((unsigned char *) "E", 1 );
766
}
767
#endif
768
 
769
/******************************************************************************
770
 * ninGo:
771
 *      Ask NINDY to start or continue execution of an application program
772
 *      in it's memory at the current ip.
773
 ******************************************************************************/
774
ninGo( step_flag )
775
    int step_flag;      /* 1 => run in single-step mode */
776
{
777
        if ( old_nindy ){
778
                OninGo( step_flag );
779
                return;
780
        }
781
        putpkt((unsigned char *) (step_flag ? "s" : "c"), 1 );
782
}
783
 
784
 
785
/******************************************************************************
786
 * ninMemGet:
787
 *      Read a string of bytes from NINDY's address space (960 memory).
788
 ******************************************************************************/
789
int
790
ninMemGet(ninaddr, hostaddr, len)
791
     long ninaddr;      /* Source address, in the 960 memory space      */
792
     unsigned char *hostaddr;   /* Destination address, in our memory space */
793
     int len;           /* Number of bytes to read                      */
794
{
795
        unsigned char buf[BUFSIZE+20];
796
        int cnt;                /* Number of bytes in next transfer     */
797
        int origlen = len;
798
 
799
        if ( old_nindy ){
800
                OninMemGet(ninaddr, hostaddr, len);
801
                return;
802
        }
803
 
804
        for ( ; len > 0; len -= BUFSIZE ){
805
                cnt = len > BUFSIZE ? BUFSIZE : len;
806
 
807
                buf[0] = 'm';
808
                store_unsigned_integer (&buf[1], 4, ninaddr);
809
                buf[5] = cnt & 0xff;
810
                buf[6] = (cnt>>8) & 0xff;
811
 
812
                send( buf, 7, hostaddr );
813
 
814
                ninaddr += cnt;
815
                hostaddr += cnt;
816
        }
817
        return origlen;
818
}
819
 
820
 
821
/******************************************************************************
822
 * ninMemPut:
823
 *      Write a string of bytes into NINDY's address space (960 memory).
824
 ******************************************************************************/
825
int
826
ninMemPut( ninaddr, hostaddr, len )
827
     long ninaddr;      /* Destination address, in NINDY memory space   */
828
     unsigned char *hostaddr;   /* Source address, in our memory space  */
829
     int len;           /* Number of bytes to write                     */
830
{
831
        unsigned char buf[BUFSIZE+20];
832
        int cnt;                /* Number of bytes in next transfer     */
833
        int origlen = len;
834
 
835
        if ( old_nindy ){
836
                OninMemPut( ninaddr, hostaddr, len );
837
                return;
838
        }
839
        for ( ; len > 0; len -= BUFSIZE ){
840
                cnt = len > BUFSIZE ? BUFSIZE : len;
841
 
842
                buf[0] = 'M';
843
                store_unsigned_integer (&buf[1], 4, ninaddr);
844
                memcpy(buf + 5, hostaddr, cnt);
845
                send( buf, cnt+5, NULL );
846
 
847
                ninaddr += cnt;
848
                hostaddr += cnt;
849
        }
850
        return origlen;
851
}
852
 
853
/******************************************************************************
854
 * ninRegGet:
855
 *      Retrieve the contents of a 960 register, and return them as a long
856
 *      in host byte order.
857
 *
858
 *      THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND
859
 *      ip/ac/pc/tc REGISTERS.
860
 *
861
 ******************************************************************************/
862
long
863
ninRegGet( regname )
864
    char *regname;      /* Register name recognized by NINDY, subject to the
865
                         * above limitations.
866
                         */
867
{
868
        unsigned char outbuf[10];
869
        unsigned char inbuf[20];
870
 
871
        if ( old_nindy ){
872
                return OninRegGet( regname );
873
        }
874
 
875
        sprintf( outbuf, "u%s:", regname );
876
        send( outbuf, strlen(outbuf), inbuf );
877
        return extract_unsigned_integer (inbuf, 4);
878
}
879
 
880
/******************************************************************************
881
 * ninRegPut:
882
 *      Set the contents of a 960 register.
883
 *
884
 *      THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND
885
 *      ip/ac/pc/tc REGISTERS.
886
 *
887
 ******************************************************************************/
888
ninRegPut( regname, val )
889
    char *regname;      /* Register name recognized by NINDY, subject to the
890
                         * above limitations.
891
                         */
892
    long val;           /* New contents of register, in host byte-order */
893
{
894
        unsigned char buf[20];
895
        int len;
896
 
897
        if ( old_nindy ){
898
                OninRegPut( regname, val );
899
                return;
900
        }
901
 
902
        sprintf( buf, "U%s:", regname );
903
        len = strlen(buf);
904
        store_unsigned_integer (&buf[len], 4, val);
905
        send( buf, len+4, NULL );
906
}
907
 
908
/******************************************************************************
909
 * ninRegsGet:
910
 *      Get a dump of the contents of the entire 960 register set.  The
911
 *      individual registers appear in the dump in the following order:
912
 *
913
 *              pfp  sp   rip  r3   r4   r5   r6   r7
914
 *              r8   r9   r10  r11  r12  r13  r14  r15
915
 *              g0   g1   g2   g3   g4   g5   g6   g7
916
 *              g8   g9   g10  g11  g12  g13  g14  fp
917
 *              pc   ac   ip   tc   fp0  fp1  fp2  fp3
918
 *
919
 *      Each individual register comprises exactly 4 bytes, except for
920
 *      fp0-fp3, which are 8 bytes.  All register values are in 960
921
 *      (little-endian) byte order.
922
 *
923
 ******************************************************************************/
924
ninRegsGet( regp )
925
    unsigned char *regp;                /* Where to place the register dump */
926
{
927
        if ( old_nindy ){
928
                OninRegsGet( regp );
929
                return;
930
        }
931
        send( (unsigned char *) "r", 1, regp );
932
}
933
 
934
 
935
/******************************************************************************
936
 * ninRegsPut:
937
 *      Initialize the entire 960 register set to a specified set of values.
938
 *      The format of the register value data should be the same as that
939
 *      returned by ninRegsGet.
940
 *
941
 * WARNING:
942
 *      All register values must be in 960 (little-endian) byte order.
943
 *
944
 ******************************************************************************/
945
ninRegsPut( regp )
946
    char *regp;         /* Pointer to desired values of registers */
947
{
948
/* Number of bytes that we send to nindy.  I believe this is defined by
949
   the protocol (it does not agree with REGISTER_BYTES).  */
950
#define NINDY_REGISTER_BYTES    ((36*4) + (4*8))
951
        unsigned char buf[NINDY_REGISTER_BYTES+10];
952
 
953
        if ( old_nindy ){
954
                OninRegsPut( regp );
955
                return;
956
        }
957
 
958
        buf[0] = 'R';
959
        memcpy(buf+1,  regp, NINDY_REGISTER_BYTES );
960
        send( buf, NINDY_REGISTER_BYTES+1, NULL );
961
}
962
 
963
 
964
/******************************************************************************
965
 * ninReset:
966
 *      Ask NINDY to perform a soft reset; wait for the reset to complete.
967
 *
968
 ******************************************************************************/
969
ninReset()
970
{
971
        unsigned char ack;
972
 
973
        if ( old_nindy ){
974
                OninReset();
975
                return;
976
        }
977
 
978
        while (1){
979
                putpkt((unsigned char *) "X", 1 );
980
                while (1){
981
                        if ( !rdnin(&ack,1,5) ){
982
                                /* Timed out */
983
                                break;          /* Resend */
984
                        }
985
                        if ( ack == '+' ){
986
                                return;
987
                        }
988
                }
989
        }
990
}
991
 
992
 
993
/******************************************************************************
994
 * ninSrq:
995
 *      Assume NINDY has stopped execution of the 960 application program in
996
 *      order to process a host service request (srq).  Ask NINDY for the
997
 *      srq arguments, perform the requested service, and send an "srq
998
 *      complete" message so NINDY will return control to the application.
999
 *
1000
 ******************************************************************************/
1001
ninSrq()
1002
{
1003
  /* FIXME: Imposes arbitrary limits on lengths of pathnames and such.  */
1004
        unsigned char buf[BUFSIZE];
1005
        int retcode;
1006
        unsigned char srqnum;
1007
        int i;
1008
        int offset;
1009
        int arg[MAX_SRQ_ARGS];
1010
 
1011
        if ( old_nindy ){
1012
                OninSrq();
1013
                return;
1014
        }
1015
 
1016
 
1017
        /* Get srq number and arguments
1018
         */
1019
        send((unsigned char *) "!", 1, buf );
1020
 
1021
        srqnum = buf[0];
1022
        for  ( i=0, offset=1; i < MAX_SRQ_ARGS; i++, offset+=4 ){
1023
                arg[i] = extract_unsigned_integer (&buf[offset], 4);
1024
        }
1025
 
1026
        /* Process Srq
1027
         */
1028
        switch( srqnum ){
1029
        case BS_CLOSE:
1030
                /* args: file descriptor */
1031
                if ( arg[0] > 2 ){
1032
                        retcode = close( arg[0] );
1033
                } else {
1034
                        retcode = 0;
1035
                }
1036
                break;
1037
        case BS_CREAT:
1038
                /* args: filename, mode */
1039
                ninStrGet( arg[0], buf );
1040
                retcode = creat(buf,arg[1]);
1041
                break;
1042
        case BS_OPEN:
1043
                /* args: filename, flags, mode */
1044
                ninStrGet( arg[0], buf );
1045
                retcode = open(buf,arg[1],arg[2]);
1046
                break;
1047
        case BS_READ:
1048
                /* args: file descriptor, buffer, count */
1049
                retcode = read(arg[0],buf,arg[2]);
1050
                if ( retcode > 0 ){
1051
                        ninMemPut( arg[1], buf, retcode );
1052
                }
1053
                break;
1054
        case BS_SEEK:
1055
                /* args: file descriptor, offset, whence */
1056
                retcode = lseek(arg[0],arg[1],arg[2]);
1057
                break;
1058
        case BS_WRITE:
1059
                /* args: file descriptor, buffer, count */
1060
                ninMemGet( arg[1], buf, arg[2] );
1061
                retcode = write(arg[0],buf,arg[2]);
1062
                break;
1063
        default:
1064
                retcode = -1;
1065
                break;
1066
        }
1067
 
1068
        /* Send request termination status to NINDY
1069
         */
1070
        buf[0] = 'e';
1071
        store_unsigned_integer (&buf[1], 4, retcode);
1072
        send( buf, 5, NULL );
1073
}
1074
 
1075
 
1076
/******************************************************************************
1077
 * ninStopWhy:
1078
 *      Assume the application program has stopped (i.e., a DLE was received
1079
 *      from NINDY).  Ask NINDY for status information describing the
1080
 *      reason for the halt.
1081
 *
1082
 *      Returns a non-zero value if the user program has exited, 0 otherwise.
1083
 *      Also returns the following information, through passed pointers:
1084
 *           - why: an exit code if program the exited; otherwise the reason
1085
 *                      why the program halted (see stop.h for values).
1086
 *          - contents of register ip (little-endian byte order)
1087
 *          - contents of register sp (little-endian byte order)
1088
 *          - contents of register fp (little-endian byte order)
1089
 ******************************************************************************/
1090
char
1091
ninStopWhy( whyp, ipp, fpp, spp )
1092
    unsigned char *whyp; /* Return the 'why' code through this pointer  */
1093
    long *ipp;  /* Return contents of register ip through this pointer  */
1094
    long *fpp;  /* Return contents of register fp through this pointer  */
1095
    long *spp;  /* Return contents of register sp through this pointer  */
1096
{
1097
        unsigned char buf[30];
1098
        extern char OninStopWhy ();
1099
 
1100
        if ( old_nindy ){
1101
                return OninStopWhy( whyp, ipp, fpp, spp );
1102
        }
1103
        send((unsigned char *) "?", 1, buf );
1104
 
1105
        *whyp = buf[1];
1106
        memcpy ((char *)ipp, &buf[2],  sizeof (*ipp));
1107
        memcpy ((char *)fpp, &buf[6],  sizeof (*ipp));
1108
        memcpy ((char *)spp, &buf[10], sizeof (*ipp));
1109
        return buf[0];
1110
}
1111
 
1112
/******************************************************************************
1113
 * ninStrGet:
1114
 *      Read a '\0'-terminated string of data out of the 960 memory space.
1115
 *
1116
 ******************************************************************************/
1117
static
1118
ninStrGet( ninaddr, hostaddr )
1119
     unsigned long ninaddr;     /* Address of string in NINDY memory space */
1120
     unsigned char *hostaddr;   /* Address of the buffer to which string should
1121
                                 *      be copied.
1122
                                 */
1123
{
1124
        unsigned char cmd[5];
1125
 
1126
        cmd[0] = '"';
1127
        store_unsigned_integer (&cmd[1], 4, ninaddr);
1128
        send( cmd, 5, hostaddr );
1129
}
1130
 
1131
#if 0
1132
/* Not used.  */
1133
 
1134
/******************************************************************************
1135
 * ninVersion:
1136
 *      Ask NINDY for version information about itself.
1137
 *      The information is sent as an ascii string in the form "x.xx,<arch>",
1138
 *      where,
1139
 *              x.xx    is the version number
1140
 *              <arch>  is the processor architecture: "KA", "KB", "MC", "CA" *
1141
 *
1142
 ******************************************************************************/
1143
int
1144
ninVersion( p )
1145
     unsigned char *p;          /* Where to place version string */
1146
{
1147
 
1148
        if ( old_nindy ){
1149
                return OninVersion( p );
1150
        }
1151
        send((unsigned char *) "v", 1, p );
1152
        return strlen(p);
1153
}
1154
#endif /* 0 */

powered by: WebSVN 2.1.0

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