URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
Compare Revisions
- This comparison shows the changes necessary to convert path
/or1k/tags/start/gdb-5.0/gdb/nindy-share
- from Rev 579 to Rev 1765
- ↔ Reverse comparison
Rev 579 → Rev 1765
/Onindy.c
0,0 → 1,743
/* This file is part of GDB. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
/* This started out life as code shared between the nindy monitor and |
GDB. For various reasons, this is no longer true. Eventually, it |
probably should be merged into remote-nindy.c. */ |
|
/****************************************************************************** |
* |
* NINDY INTERFACE ROUTINES |
* |
* This version of the NINDY interface routines supports NINDY versions |
* 2.13 and older. The older versions used a hex communication protocol, |
* instead of the (faster) current binary protocol. These routines have |
* been renamed by prepending the letter 'O' to their names, to avoid |
* conflict with the current version. The old versions are kept only for |
* backward compatibility, and well disappear in a future release. |
* |
**************************************************************************/ |
|
/* Having these in a separate file from nindy.c is really ugly, and should |
be merged with nindy.c. */ |
|
#include <stdio.h> |
#if 0 |
#include <sys/ioctl.h> |
#include <sys/types.h> /* Needed by file.h on Sys V */ |
#include <sys/file.h> |
#include <signal.h> |
#include <sys/stat.h> |
#include <fcntl.h> /* Needed on Sys V */ |
#include "ttycntl.h" |
#endif |
#include "defs.h" |
#include "serial.h" |
|
#include "block_io.h" |
#include "gdb_wait.h" |
#include "env.h" |
|
/* Number of bytes that we send to nindy. I believe this is defined by |
the protocol (it does not agree with REGISTER_BYTES). */ |
#define OLD_NINDY_REGISTER_BYTES ((36*4) + (4*8)) |
|
extern int quiet; /* 1 => stifle unnecessary messages */ |
|
/* tty connected to 960/NINDY board. */ |
extern serial_t nindy_serial; |
|
static OninStrGet(); |
|
/**************************** |
* * |
* MISCELLANEOUS UTILTIES * |
* * |
****************************/ |
|
|
/****************************************************************************** |
* fromhex: |
* Convert a hex ascii digit h to a binary integer |
******************************************************************************/ |
static |
int |
fromhex( h ) |
int h; |
{ |
if (h >= '0' && h <= '9'){ |
h -= '0'; |
} else if (h >= 'a' && h <= 'f'){ |
h -= 'a' - 10; |
} else { |
h = 0; |
} |
return (h & 0xff); |
} |
|
|
/****************************************************************************** |
* hexbin: |
* Convert a string of ASCII hex digits to a string of binary bytes. |
******************************************************************************/ |
static |
hexbin( n, hexp, binp ) |
int n; /* Number of bytes to convert (twice this many digits)*/ |
char *hexp; /* Get hex from here */ |
char *binp; /* Put binary here */ |
{ |
while ( n-- ){ |
*binp++ = (fromhex(*hexp) << 4) | fromhex(*(hexp+1)); |
hexp += 2; |
} |
} |
|
|
/****************************************************************************** |
* binhex: |
* Convert a string of binary bytes to a string of ASCII hex digits |
******************************************************************************/ |
static |
binhex( n, binp, hexp ) |
int n; /* Number of bytes to convert */ |
char *binp; /* Get binary from here */ |
char *hexp; /* Place hex here */ |
{ |
static char tohex[] = "0123456789abcdef"; |
|
while ( n-- ){ |
*hexp++ = tohex[ (*binp >> 4) & 0xf ]; |
*hexp++ = tohex[ *binp & 0xf ]; |
binp++; |
} |
} |
|
/****************************************************************************** |
* byte_order: |
* If the host byte order is different from 960 byte order (i.e., the |
* host is big-endian), reverse the bytes in the passed value; otherwise, |
* return the passed value unchanged. |
* |
******************************************************************************/ |
static |
long |
byte_order( n ) |
long n; |
{ |
long rev; |
int i; |
static short test = 0x1234; |
|
if (*((char *) &test) == 0x12) { |
/* |
* Big-endian host, swap the bytes. |
*/ |
rev = 0; |
for ( i = 0; i < sizeof(n); i++ ){ |
rev <<= 8; |
rev |= n & 0xff; |
n >>= 8; |
} |
n = rev; |
} |
return n; |
} |
|
/****************************************************************************** |
* say: |
* This is a printf that takes at most two arguments (in addition to the |
* format string) and that outputs nothing if verbose output has been |
* suppressed. |
******************************************************************************/ |
static |
say( fmt, arg1, arg2 ) |
char *fmt; |
int arg1, arg2; |
{ |
if ( !quiet ){ |
printf( fmt, arg1, arg2 ); |
fflush( stdout ); |
} |
} |
|
/***************************** |
* * |
* LOW-LEVEL COMMUNICATION * |
* * |
*****************************/ |
|
/* Read a single character from the remote end. */ |
|
static int |
readchar() |
{ |
/* FIXME: Do we really want to be reading without a timeout? */ |
return SERIAL_READCHAR (nindy_serial, -1); |
} |
|
/****************************************************************************** |
* getpkt: |
* Read a packet from a remote NINDY, with error checking, and return |
* it in the indicated buffer. |
******************************************************************************/ |
static |
getpkt (buf) |
char *buf; |
{ |
unsigned char recv; /* Checksum received */ |
unsigned char csum; /* Checksum calculated */ |
char *bp; /* Poointer into the buffer */ |
int c; |
|
while (1){ |
csum = 0; |
bp = buf; |
/* FIXME: check for error from readchar (). */ |
while ( (c = readchar()) != '#' ){ |
*bp++ = c; |
csum += c; |
} |
*bp = 0; |
|
/* FIXME: check for error from readchar (). */ |
recv = fromhex(readchar()) << 4; |
recv |= fromhex(readchar()); |
if ( csum == recv ){ |
break; |
} |
|
fprintf(stderr, |
"Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n", |
recv, csum ); |
SERIAL_WRITE (nindy_serial, "-", 1); |
} |
|
SERIAL_WRITE (nindy_serial, "+", 1); |
} |
|
|
/****************************************************************************** |
* putpkt: |
* Checksum and send a gdb command to a remote NINDY, and wait for |
* positive acknowledgement. |
* |
******************************************************************************/ |
static |
putpkt( cmd ) |
char *cmd; /* Command to be sent, without lead ^P (\020) |
* or trailing checksum |
*/ |
{ |
char ack; /* Response received from NINDY */ |
char checksum[4]; |
char *p; |
unsigned int s; |
char resend; |
|
for ( s='\020', p=cmd; *p; p++ ){ |
s += *p; |
} |
sprintf( checksum, "#%02x", s & 0xff ); |
|
/* Send checksummed message over and over until we get a positive ack |
*/ |
resend = 1; |
do { |
if ( resend ) { |
SERIAL_WRITE ( nindy_serial, "\020", 1 ); |
SERIAL_WRITE( nindy_serial, cmd, strlen(cmd) ); |
SERIAL_WRITE( nindy_serial, checksum, strlen(checksum) ); |
} |
/* FIXME: do we really want to be reading without timeout? */ |
ack = SERIAL_READCHAR (nindy_serial, -1); |
if (ack < 0) |
{ |
fprintf (stderr, "error reading from serial port\n"); |
} |
if ( ack == '-' ){ |
fprintf( stderr, "Remote NAK, resending\r\n" ); |
resend = 1; |
} else if ( ack != '+' ){ |
fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack ); |
resend = 0; |
} |
} while ( ack != '+' ); |
} |
|
|
|
/****************************************************************************** |
* send: |
* Send a message to a remote NINDY and return the reply in the same |
* buffer (clobbers the input message). Check for error responses |
* as indicated by the second argument. |
* |
******************************************************************************/ |
static |
send( buf, ack_required ) |
char *buf; /* Message to be sent to NINDY; replaced by |
* NINDY's response. |
*/ |
int ack_required; /* 1 means NINDY's response MUST be either "X00" (no |
* error) or an error code "Xnn". |
* 0 means the it's OK as long as it doesn't |
* begin with "Xnn". |
*/ |
{ |
int errnum; |
static char *errmsg[] = { |
"", /* X00 */ |
"Buffer overflow", /* X01 */ |
"Unknown command", /* X02 */ |
"Wrong amount of data to load register(s)", /* X03 */ |
"Missing command argument(s)", /* X04 */ |
"Odd number of digits sent to load memory", /* X05 */ |
"Unknown register name", /* X06 */ |
"No such memory segment", /* X07 */ |
"No breakpoint available", /* X08 */ |
"Can't set requested baud rate", /* X09 */ |
}; |
# define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) ) |
|
static char err0[] = "NINDY failed to acknowledge command: <%s>\r\n"; |
static char err1[] = "Unknown error response from NINDY: <%s>\r\n"; |
static char err2[] = "Error response %s from NINDY: %s\r\n"; |
|
putpkt (buf); |
getpkt (buf); |
|
if ( buf[0] != 'X' ){ |
if ( ack_required ){ |
fprintf( stderr, err0, buf ); |
abort(); |
} |
|
} else if ( strcmp(buf,"X00") ){ |
sscanf( &buf[1], "%x", &errnum ); |
if ( errnum > NUMERRS ){ |
fprintf( stderr, err1, buf ); |
} else{ |
fprintf( stderr, err2, buf, errmsg[errnum] ); |
} |
abort(); |
} |
} |
|
/********************************** |
* * |
* NINDY INTERFACE ROUTINES * |
* * |
* ninConnect *MUST* be the first * |
* one of these routines called. * |
**********************************/ |
|
/****************************************************************************** |
* ninBptDel: |
* Ask NINDY to delete the specified type of *hardware* breakpoint at |
* the specified address. If the 'addr' is -1, all breakpoints of |
* the specified type are deleted. |
******************************************************************************/ |
OninBptDel( addr, data ) |
long addr; /* Address in 960 memory */ |
int data; /* '1' => data bkpt, '0' => instruction breakpoint */ |
{ |
char buf[100]; |
|
if ( addr == -1 ){ |
sprintf( buf, "b%c", data ? '1' : '0' ); |
} else { |
sprintf( buf, "b%c%x", data ? '1' : '0', addr ); |
} |
return send( buf, 0 ); |
} |
|
|
/****************************************************************************** |
* ninBptSet: |
* Ask NINDY to set the specified type of *hardware* breakpoint at |
* the specified address. |
******************************************************************************/ |
OninBptSet( addr, data ) |
long addr; /* Address in 960 memory */ |
int data; /* '1' => data bkpt, '0' => instruction breakpoint */ |
{ |
char buf[100]; |
|
sprintf( buf, "B%c%x", data ? '1' : '0', addr ); |
return send( buf, 0 ); |
} |
|
/****************************************************************************** |
* ninGdbExit: |
* Ask NINDY to leave GDB mode and print a NINDY prompt. |
* Since it'll no longer be in GDB mode, don't wait for a response. |
******************************************************************************/ |
OninGdbExit() |
{ |
putpkt( "E" ); |
} |
|
/****************************************************************************** |
* ninGo: |
* Ask NINDY to start or continue execution of an application program |
* in it's memory at the current ip. |
******************************************************************************/ |
OninGo( step_flag ) |
int step_flag; /* 1 => run in single-step mode */ |
{ |
putpkt( step_flag ? "s" : "c" ); |
} |
|
|
/****************************************************************************** |
* ninMemGet: |
* Read a string of bytes from NINDY's address space (960 memory). |
******************************************************************************/ |
OninMemGet(ninaddr, hostaddr, len) |
long ninaddr; /* Source address, in the 960 memory space */ |
char *hostaddr; /* Destination address, in our memory space */ |
int len; /* Number of bytes to read */ |
{ |
/* How much do we send at a time? */ |
#define OLD_NINDY_MEMBYTES 1024 |
/* Buffer: hex in, binary out */ |
char buf[2*OLD_NINDY_MEMBYTES+20]; |
|
int cnt; /* Number of bytes in next transfer */ |
|
for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){ |
cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len; |
|
sprintf( buf, "m%x,%x", ninaddr, cnt ); |
send( buf, 0 ); |
hexbin( cnt, buf, hostaddr ); |
|
ninaddr += cnt; |
hostaddr += cnt; |
} |
} |
|
|
/****************************************************************************** |
* ninMemPut: |
* Write a string of bytes into NINDY's address space (960 memory). |
******************************************************************************/ |
OninMemPut( destaddr, srcaddr, len ) |
long destaddr; /* Destination address, in NINDY memory space */ |
char *srcaddr; /* Source address, in our memory space */ |
int len; /* Number of bytes to write */ |
{ |
char buf[2*OLD_NINDY_MEMBYTES+20]; /* Buffer: binary in, hex out */ |
char *p; /* Pointer into buffer */ |
int cnt; /* Number of bytes in next transfer */ |
|
for ( ; len > 0; len -= OLD_NINDY_MEMBYTES ){ |
cnt = len > OLD_NINDY_MEMBYTES ? OLD_NINDY_MEMBYTES : len; |
|
sprintf( buf, "M%x,", destaddr ); |
p = buf + strlen(buf); |
binhex( cnt, srcaddr, p ); |
*(p+(2*cnt)) = '\0'; |
send( buf, 1 ); |
|
srcaddr += cnt; |
destaddr += cnt; |
} |
} |
|
/****************************************************************************** |
* ninRegGet: |
* Retrieve the contents of a 960 register, and return them as a long |
* in host byte order. |
* |
* THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND |
* ip/ac/pc/tc REGISTERS. |
* |
******************************************************************************/ |
long |
OninRegGet( regname ) |
char *regname; /* Register name recognized by NINDY, subject to the |
* above limitations. |
*/ |
{ |
char buf[200]; |
long val; |
|
sprintf( buf, "u%s", regname ); |
send( buf, 0 ); |
hexbin( 4, buf, (char *)&val ); |
return byte_order(val); |
} |
|
/****************************************************************************** |
* ninRegPut: |
* Set the contents of a 960 register. |
* |
* THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND |
* ip/ac/pc/tc REGISTERS. |
* |
******************************************************************************/ |
OninRegPut( regname, val ) |
char *regname; /* Register name recognized by NINDY, subject to the |
* above limitations. |
*/ |
long val; /* New contents of register, in host byte-order */ |
{ |
char buf[200]; |
|
sprintf( buf, "U%s,%08x", regname, byte_order(val) ); |
send( buf, 1 ); |
} |
|
/****************************************************************************** |
* ninRegsGet: |
* Get a dump of the contents of the entire 960 register set. The |
* individual registers appear in the dump in the following order: |
* |
* pfp sp rip r3 r4 r5 r6 r7 |
* r8 r9 r10 r11 r12 r13 r14 r15 |
* g0 g1 g2 g3 g4 g5 g6 g7 |
* g8 g9 g10 g11 g12 g13 g14 fp |
* pc ac ip tc fp0 fp1 fp2 fp3 |
* |
* Each individual register comprises exactly 4 bytes, except for |
* fp0-fp3, which are 8 bytes. |
* |
* WARNING: |
* Each register value is in 960 (little-endian) byte order. |
* |
******************************************************************************/ |
OninRegsGet( regp ) |
char *regp; /* Where to place the register dump */ |
{ |
char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */ |
|
strcpy( buf, "r" ); |
send( buf, 0 ); |
hexbin( OLD_NINDY_REGISTER_BYTES, buf, regp ); |
} |
|
/****************************************************************************** |
* ninRegsPut: |
* Initialize the entire 960 register set to a specified set of values. |
* The format of the register value data should be the same as that |
* returned by ninRegsGet. |
* |
* WARNING: |
* Each register value should be in 960 (little-endian) byte order. |
* |
******************************************************************************/ |
OninRegsPut( regp ) |
char *regp; /* Pointer to desired values of registers */ |
{ |
char buf[(2*OLD_NINDY_REGISTER_BYTES)+10]; /* Registers in ASCII hex */ |
|
buf[0] = 'R'; |
binhex( OLD_NINDY_REGISTER_BYTES, regp, buf+1 ); |
buf[ (2*OLD_NINDY_REGISTER_BYTES)+1 ] = '\0'; |
|
send( buf, 1 ); |
} |
|
|
/****************************************************************************** |
* ninReset: |
* Ask NINDY to perform a soft reset; wait for the reset to complete. |
******************************************************************************/ |
OninReset() |
{ |
|
putpkt( "X" ); |
/* FIXME: check for error from readchar (). */ |
while ( readchar() != '+' ){ |
; |
} |
} |
|
|
/****************************************************************************** |
* ninSrq: |
* Assume NINDY has stopped execution of the 960 application program in |
* order to process a host service request (srq). Ask NINDY for the |
* srq arguments, perform the requested service, and send an "srq |
* complete" message so NINDY will return control to the application. |
* |
******************************************************************************/ |
OninSrq() |
{ |
/* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */ |
char buf[BUFSIZE]; |
int retcode; |
unsigned char srqnum; |
char *p; |
char *argp; |
int nargs; |
int arg[MAX_SRQ_ARGS]; |
|
|
/* Get srq number and arguments |
*/ |
strcpy( buf, "!" ); |
send( buf, 0 ); |
hexbin( 1, buf, (char *)&srqnum ); |
|
/* Set up array of pointers the each of the individual |
* comma-separated args |
*/ |
nargs=0; |
argp = p = buf+2; |
while ( 1 ){ |
while ( *p != ',' && *p != '\0' ){ |
p++; |
} |
sscanf( argp, "%x", &arg[nargs++] ); |
if ( *p == '\0' || nargs == MAX_SRQ_ARGS ){ |
break; |
} |
argp = ++p; |
} |
|
/* Process Srq |
*/ |
switch( srqnum ){ |
case BS_CLOSE: |
/* args: file descriptor */ |
if ( arg[0] > 2 ){ |
retcode = close( arg[0] ); |
} else { |
retcode = 0; |
} |
break; |
case BS_CREAT: |
/* args: filename, mode */ |
OninStrGet( arg[0], buf ); |
retcode = creat(buf,arg[1]); |
break; |
case BS_OPEN: |
/* args: filename, flags, mode */ |
OninStrGet( arg[0], buf ); |
retcode = open(buf,arg[1],arg[2]); |
break; |
case BS_READ: |
/* args: file descriptor, buffer, count */ |
retcode = read(arg[0],buf,arg[2]); |
if ( retcode > 0 ){ |
OninMemPut( arg[1], buf, retcode ); |
} |
break; |
case BS_SEEK: |
/* args: file descriptor, offset, whence */ |
retcode = lseek(arg[0],arg[1],arg[2]); |
break; |
case BS_WRITE: |
/* args: file descriptor, buffer, count */ |
OninMemGet( arg[1], buf, arg[2] ); |
retcode = write(arg[0],buf,arg[2]); |
break; |
default: |
retcode = -1; |
break; |
} |
|
/* Tell NINDY to continue |
*/ |
sprintf( buf, "e%x", retcode ); |
send( buf, 1 ); |
} |
|
|
/****************************************************************************** |
* ninStopWhy: |
* Assume the application program has stopped (i.e., a DLE was received |
* from NINDY). Ask NINDY for status information describing the |
* reason for the halt. |
* |
* Returns a non-zero value if the user program has exited, 0 otherwise. |
* Also returns the following information, through passed pointers: |
* - why: an exit code if program the exited; otherwise the reason |
* why the program halted (see stop.h for values). |
* - contents of register ip (little-endian byte order) |
* - contents of register sp (little-endian byte order) |
* - contents of register fp (little-endian byte order) |
******************************************************************************/ |
char |
OninStopWhy( whyp, ipp, fpp, spp ) |
char *whyp; /* Return the 'why' code through this pointer */ |
char *ipp; /* Return contents of register ip through this pointer */ |
char *fpp; /* Return contents of register fp through this pointer */ |
char *spp; /* Return contents of register sp through this pointer */ |
{ |
char buf[30]; |
char stop_exit; |
|
strcpy( buf, "?" ); |
send( buf, 0 ); |
hexbin( 1, buf, &stop_exit ); |
hexbin( 1, buf+2, whyp ); |
hexbin( 4, buf+4, ipp ); |
hexbin( 4, buf+12, fpp ); |
hexbin( 4, buf+20, spp ); |
return stop_exit; |
} |
|
/****************************************************************************** |
* ninStrGet: |
* Read a '\0'-terminated string of data out of the 960 memory space. |
* |
******************************************************************************/ |
static |
OninStrGet( ninaddr, hostaddr ) |
unsigned long ninaddr; /* Address of string in NINDY memory space */ |
char *hostaddr; /* Address of the buffer to which string should |
* be copied. |
*/ |
{ |
/* FIXME: seems to be an arbitrary limit on the length of the string. */ |
char buf[BUFSIZE]; /* String as 2 ASCII hex digits per byte */ |
int numchars; /* Length of string in bytes. */ |
|
sprintf( buf, "\"%x", ninaddr ); |
send( buf, 0 ); |
numchars = strlen(buf)/2; |
hexbin( numchars, buf, hostaddr ); |
hostaddr[numchars] = '\0'; |
} |
|
#if 0 |
/* never used. */ |
|
/****************************************************************************** |
* ninVersion: |
* Ask NINDY for version information about itself. |
* The information is sent as an ascii string in the form "x.xx,<arch>", |
* where, |
* x.xx is the version number |
* <arch> is the processor architecture: "KA", "KB", "MC", "CA" * |
* |
******************************************************************************/ |
int |
OninVersion( p ) |
char *p; /* Where to place version string */ |
{ |
/* FIXME: this is an arbitrary limit on the length of version string. */ |
char buf[BUFSIZE]; |
|
strcpy( buf, "v" ); |
send( buf, 0 ); |
strcpy( p, buf ); |
return strlen( buf ); |
} |
#endif |
/nindy.c
0,0 → 1,1154
/* This file is part of GDB. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
/* This started out life as code shared between the nindy monitor and |
GDB. For various reasons, this is no longer true. Eventually, it |
probably should be merged into remote-nindy.c. */ |
|
/****************************************************************************** |
* |
* NINDY INTERFACE ROUTINES |
* |
* The caller of these routines should be aware that: |
* |
* (1) ninConnect() should be called to open communications with the |
* remote NINDY board before any of the other routines are invoked. |
* |
* (2) almost all interactions are driven by the host: nindy sends information |
* in response to host commands. |
* |
* (3) the lone exception to (2) is the single character DLE (^P, 0x10). |
* Receipt of a DLE from NINDY indicates that the application program |
* running under NINDY has stopped execution and that NINDY is now |
* available to talk to the host (all other communication received after |
* the application has been started should be presumed to come from the |
* application and should be passed on by the host to stdout). |
* |
* (4) the reason the application program stopped can be determined with the |
* ninStopWhy() function. There are three classes of stop reasons: |
* |
* (a) the application has terminated execution. |
* The host should take appropriate action. |
* |
* (b) the application had a fault or trace event. |
* The host should take appropriate action. |
* |
* (c) the application wishes to make a service request (srq) of the host; |
* e.g., to open/close a file, read/write a file, etc. The ninSrq() |
* function should be called to determine the nature of the request |
* and process it. |
*/ |
|
#include <stdio.h> |
#include "defs.h" |
#include "serial.h" |
#ifdef ANSI_PROTOTYPES |
#include <stdarg.h> |
#else |
#include <varargs.h> |
#endif |
|
#if !defined (HAVE_TERMIOS) && !defined (HAVE_TERMIO) && !defined (HAVE_SGTTY) |
#define HAVE_SGTTY |
#endif |
|
#ifdef HAVE_SGTTY |
#include <sys/ioctl.h> |
#endif |
|
#include <sys/types.h> /* Needed by file.h on Sys V */ |
#include <sys/file.h> |
#include <signal.h> |
#include <sys/stat.h> |
|
#if 0 |
#include "ttycntl.h" |
#endif |
#include "block_io.h" |
#include "gdb_wait.h" |
#include "env.h" |
|
#define DLE 0x10 /* ^P */ |
#define XON 0x11 /* ^Q */ |
#define XOFF 0x13 /* ^S */ |
#define ESC 0x1b |
|
#define TIMEOUT -1 |
|
int quiet = 0; /* 1 => stifle unnecessary messages */ |
serial_t nindy_serial; |
|
static int old_nindy = 0; /* 1 => use old (hex) communication protocol */ |
static ninStrGet(); |
|
/**************************** |
* * |
* MISCELLANEOUS UTILTIES * |
* * |
****************************/ |
|
/****************************************************************************** |
* say: |
* This is a printf that takes at most two arguments (in addition to the |
* format string) and that outputs nothing if verbose output has been |
* suppressed. |
*****************************************************************************/ |
|
/* VARARGS */ |
static void |
#ifdef ANSI_PROTOTYPES |
say (char *fmt, ...) |
#else |
say (va_alist) |
va_dcl |
#endif |
{ |
va_list args; |
#ifdef ANSI_PROTOTYPES |
va_start(args, fmt); |
#else |
char *fmt; |
|
va_start (args); |
fmt = va_arg (args, char *); |
#endif |
|
if (!quiet) |
{ |
vfprintf_unfiltered (gdb_stdout, fmt, args); |
gdb_flush (gdb_stdout); |
} |
va_end (args); |
} |
|
/****************************************************************************** |
* exists: |
* Creates a full pathname by concatenating up to three name components |
* onto a specified base name; optionally looks up the base name as a |
* runtime environment variable; and checks to see if the file or |
* directory specified by the pathname actually exists. |
* |
* Returns: the full pathname if it exists, NULL otherwise. |
* (returned pathname is in malloc'd memory and must be freed |
* by caller). |
*****************************************************************************/ |
static char * |
exists( base, c1, c2, c3, env ) |
char *base; /* Base directory of path */ |
char *c1, *c2, *c3; /* Components (subdirectories and/or file name) to be |
* appended onto the base directory name. One or |
* more may be omitted by passing NULL pointers. |
*/ |
int env; /* If 1, '*base' is the name of an environment variable |
* to be examined for the base directory name; |
* otherwise, '*base' is the actual name of the |
* base directory. |
*/ |
{ |
struct stat buf;/* For call to 'stat' -- never examined */ |
char *path; /* Pointer to full pathname (malloc'd memory) */ |
int len; /* Length of full pathname (incl. terminator) */ |
extern char *getenv(); |
|
|
if ( env ){ |
base = getenv( base ); |
if ( base == NULL ){ |
return NULL; |
} |
} |
|
len = strlen(base) + 4; |
/* +4 for terminator and "/" before each component */ |
if ( c1 != NULL ){ |
len += strlen(c1); |
} |
if ( c2 != NULL ){ |
len += strlen(c2); |
} |
if ( c3 != NULL ){ |
len += strlen(c3); |
} |
|
path = xmalloc (len); |
|
strcpy( path, base ); |
if ( c1 != NULL ){ |
strcat( path, "/" ); |
strcat( path, c1 ); |
if ( c2 != NULL ){ |
strcat( path, "/" ); |
strcat( path, c2 ); |
if ( c3 != NULL ){ |
strcat( path, "/" ); |
strcat( path, c3 ); |
} |
} |
} |
|
if ( stat(path,&buf) != 0 ){ |
free( path ); |
path = NULL; |
} |
return path; |
} |
|
/***************************** |
* * |
* LOW-LEVEL COMMUNICATION * |
* * |
*****************************/ |
|
/* Read *exactly* N characters from the NINDY tty, and put them in |
*BUF. Translate escape sequences into single characters, counting |
each such sequence as 1 character. |
|
An escape sequence consists of ESC and a following character. The |
ESC is discarded and the other character gets bit 0x40 cleared -- |
thus ESC P == ^P, ESC S == ^S, ESC [ == ESC, etc. |
|
Return 1 if successful, 0 if more than TIMEOUT seconds pass without |
any input. */ |
|
static int |
rdnin (buf,n,timeout) |
unsigned char * buf; /* Where to place characters read */ |
int n; /* Number of characters to read */ |
int timeout; /* Timeout, in seconds */ |
{ |
int escape_seen; /* 1 => last character of a read was an ESC */ |
int c; |
|
escape_seen = 0; |
while (n) |
{ |
c = SERIAL_READCHAR (nindy_serial, timeout); |
switch (c) |
{ |
case SERIAL_ERROR: |
case SERIAL_TIMEOUT: |
case SERIAL_EOF: |
return 0; |
|
case ESC: |
escape_seen = 1; |
break; |
|
default: |
if (escape_seen) |
{ |
escape_seen = 0; |
c &= ~0x40; |
} |
*buf++ = c; |
--n; |
break; |
} |
} |
return 1; |
} |
|
|
/****************************************************************************** |
* getpkt: |
* Read a packet from a remote NINDY, with error checking, into the |
* indicated buffer. |
* |
* Return packet status byte on success, TIMEOUT on failure. |
******************************************************************************/ |
static |
int |
getpkt(buf) |
unsigned char *buf; |
{ |
int i; |
unsigned char hdr[3]; /* Packet header: |
* hdr[0] = low byte of message length |
* hdr[1] = high byte of message length |
* hdr[2] = message status |
*/ |
int cnt; /* Message length (status byte + data) */ |
unsigned char cs_calc; /* Checksum calculated */ |
unsigned char cs_recv; /* Checksum received */ |
static char errfmt[] = |
"Bad checksum (recv=0x%02x; calc=0x%02x); retrying\r\n"; |
|
while (1){ |
if ( !rdnin(hdr,3,5) ){ |
return TIMEOUT; |
} |
cnt = (hdr[1]<<8) + hdr[0] - 1; |
/* -1 for status byte (already read) */ |
|
/* Caller's buffer may only be big enough for message body, |
* without status byte and checksum, so make sure to read |
* checksum into a separate buffer. |
*/ |
if ( !rdnin(buf,cnt,5) || !rdnin(&cs_recv,1,5) ){ |
return TIMEOUT; |
} |
|
/* Calculate checksum |
*/ |
cs_calc = hdr[0] + hdr[1] + hdr[2]; |
for ( i = 0; i < cnt; i++ ){ |
cs_calc += buf[i]; |
} |
if ( cs_calc == cs_recv ){ |
SERIAL_WRITE (nindy_serial, "+", 1); |
return hdr[2]; |
} |
|
/* Bad checksum: report, send NAK, and re-receive |
*/ |
fprintf(stderr, errfmt, cs_recv, cs_calc ); |
SERIAL_WRITE (nindy_serial, "-", 1); |
} |
} |
|
|
/****************************************************************************** |
* putpkt: |
* Send a packet to NINDY, checksumming it and converting special |
* characters to escape sequences. |
******************************************************************************/ |
|
/* This macro puts the character 'c' into the buffer pointed at by 'p', |
* and increments the pointer. If 'c' is one of the 4 special characters |
* in the transmission protocol, it is converted into a 2-character |
* escape sequence. |
*/ |
#define PUTBUF(c,p) \ |
if ( c == DLE || c == ESC || c == XON || c == XOFF ){ \ |
*p++ = ESC; \ |
*p++ = c | 0x40; \ |
} else { \ |
*p++ = c; \ |
} |
|
static |
putpkt( msg, len ) |
unsigned char *msg; /* Command to be sent, without lead ^P (\020) or checksum */ |
int len; /* Number of bytes in message */ |
{ |
static char *buf = NULL;/* Local buffer -- build packet here */ |
static int maxbuf = 0; /* Current length of buffer */ |
unsigned char ack; /* Response received from NINDY */ |
unsigned char checksum; /* Packet checksum */ |
char *p; /* Pointer into buffer */ |
int lenhi, lenlo; /* High and low bytes of message length */ |
int i; |
|
|
/* Make sure local buffer is big enough. Must include space for |
* packet length, message body, and checksum. And in the worst |
* case, each character would expand into a 2-character escape |
* sequence. |
*/ |
if ( maxbuf < ((2*len)+10) ){ |
if ( buf ){ |
free( buf ); |
} |
buf = xmalloc( maxbuf=((2*len)+10) ); |
} |
|
/* Attention, NINDY! |
*/ |
SERIAL_WRITE (nindy_serial, "\020", 1); |
|
|
lenlo = len & 0xff; |
lenhi = (len>>8) & 0xff; |
checksum = lenlo + lenhi; |
p = buf; |
|
PUTBUF( lenlo, p ); |
PUTBUF( lenhi, p ); |
|
for ( i=0; i<len; i++ ){ |
PUTBUF( msg[i], p ); |
checksum += msg[i]; |
} |
|
PUTBUF( checksum, p ); |
|
/* Send checksummed message over and over until we get a positive ack |
*/ |
SERIAL_WRITE (nindy_serial, buf, p - buf); |
while (1){ |
if ( !rdnin(&ack,1,5) ){ |
/* timed out */ |
fprintf(stderr,"ACK timed out; resending\r\n"); |
/* Attention, NINDY! */ |
SERIAL_WRITE (nindy_serial, "\020", 1); |
SERIAL_WRITE (nindy_serial, buf, p - buf); |
} else if ( ack == '+' ){ |
return; |
} else if ( ack == '-' ){ |
fprintf( stderr, "Remote NAK; resending\r\n" ); |
SERIAL_WRITE (nindy_serial, buf, p - buf); |
} else { |
fprintf( stderr, "Bad ACK, ignored: <%c>\r\n", ack ); |
} |
} |
} |
|
|
|
/****************************************************************************** |
* send: |
* Send a message to a remote NINDY. Check message status byte |
* for error responses. If no error, return NINDY reponse (if any). |
******************************************************************************/ |
static |
send( out, len, in ) |
unsigned char *out; /* Message to be sent to NINDY */ |
int len; /* Number of meaningful bytes in out buffer */ |
unsigned char *in; /* Where to put response received from NINDY */ |
{ |
char *fmt; |
int status; |
static char *errmsg[] = { |
"", /* 0 */ |
"Buffer overflow", /* 1 */ |
"Unknown command", /* 2 */ |
"Wrong amount of data to load register(s)", /* 3 */ |
"Missing command argument(s)", /* 4 */ |
"Odd number of digits sent to load memory", /* 5 */ |
"Unknown register name", /* 6 */ |
"No such memory segment", /* 7 */ |
"No breakpoint available", /* 8 */ |
"Can't set requested baud rate", /* 9 */ |
}; |
# define NUMERRS ( sizeof(errmsg) / sizeof(errmsg[0]) ) |
|
static char err1[] = "Unknown error response from NINDY: #%d\r\n"; |
static char err2[] = "Error response #%d from NINDY: %s\r\n"; |
|
while (1){ |
putpkt(out,len); |
status = getpkt(in); |
if ( status == TIMEOUT ){ |
fprintf( stderr, "Response timed out; resending\r\n" ); |
} else { |
break; |
} |
} |
|
if ( status ){ |
fmt = status > NUMERRS ? err1 : err2; |
fprintf( stderr, fmt, status, errmsg[status] ); |
abort(); |
} |
} |
|
/************************ |
* * |
* BAUD RATE ROUTINES * |
* * |
************************/ |
|
/* Table of baudrates known to be acceptable to NINDY. Each baud rate |
* appears both as character string and as a Unix baud rate constant. |
*/ |
struct baudrate { |
char *string; |
int rate; |
}; |
|
static struct baudrate baudtab[] = { |
"1200", 1200, |
"2400", 2400, |
"4800", 4800, |
"9600", 9600, |
"19200", 19200, |
"38400", 38400, |
NULL, 0 /* End of table */ |
}; |
|
/****************************************************************************** |
* parse_baudrate: |
* Look up the passed baud rate in the baudrate table. If found, change |
* our internal record of the current baud rate, but don't do anything |
* about the tty just now. |
* |
* Return pointer to baudrate structure on success, NULL on failure. |
******************************************************************************/ |
static |
struct baudrate * |
parse_baudrate(s) |
char *s; /* Desired baud rate, as an ASCII (decimal) string */ |
{ |
int i; |
|
for ( i=0; baudtab[i].string != NULL; i++ ){ |
if ( !strcmp(baudtab[i].string,s) ){ |
return &baudtab[i]; |
} |
} |
return NULL; |
} |
|
/****************************************************************************** |
* try_baudrate: |
* Try speaking to NINDY via the specified file descriptor at the |
* specified baudrate. Assume success if we can send an empty command |
* with a bogus checksum and receive a NAK (response of '-') back within |
* one second. |
* |
* Return 1 on success, 0 on failure. |
***************************************************************************/ |
|
static int |
try_baudrate (serial, brp) |
serial_t serial; |
struct baudrate *brp; |
{ |
unsigned char c; |
|
/* Set specified baud rate and flush all pending input */ |
SERIAL_SETBAUDRATE (serial, brp->rate); |
tty_flush (serial); |
|
/* Send empty command with bad checksum, hope for NAK ('-') response */ |
SERIAL_WRITE (serial, "\020\0\0\001", 4); |
|
/* Anything but a quick '-', including error, eof, or timeout, means that |
this baudrate doesn't work. */ |
return SERIAL_READCHAR (serial, 1) == '-'; |
} |
|
/****************************************************************************** |
* autobaud: |
* Get NINDY talking over the specified file descriptor at the specified |
* baud rate. First see if NINDY's already talking at 'baudrate'. If |
* not, run through all the legal baudrates in 'baudtab' until one works, |
* and then tell NINDY to talk at 'baudrate' instead. |
******************************************************************************/ |
static |
autobaud( serial, brp ) |
serial_t serial; |
struct baudrate *brp; |
{ |
int i; |
int failures; |
|
say("NINDY at wrong baud rate? Trying to autobaud...\n"); |
failures = i = 0; |
while (1) |
{ |
say( "\r%s... ", baudtab[i].string ); |
if (try_baudrate(serial, &baudtab[i])) |
{ |
break; |
} |
if (baudtab[++i].string == NULL) |
{ |
/* End of table -- wraparound */ |
i = 0; |
if ( failures++ ) |
{ |
say("\nAutobaud failed again. Giving up.\n"); |
exit(1); |
} |
else |
{ |
say("\nAutobaud failed. Trying again...\n"); |
} |
} |
} |
|
/* Found NINDY's current baud rate; now change it. */ |
say("Changing NINDY baudrate to %s\n", brp->string); |
ninBaud (brp->string); |
|
/* Change our baud rate back to rate to which we just set NINDY. */ |
SERIAL_SETBAUDRATE (serial, brp->rate); |
} |
|
/********************************** |
* * |
* NINDY INTERFACE ROUTINES * |
* * |
* ninConnect *MUST* be the first * |
* one of these routines called. * |
**********************************/ |
|
|
/****************************************************************************** |
* ninBaud: |
* Ask NINDY to change the baud rate on its serial port. |
* Assumes we know the baud rate at which NINDY's currently talking. |
******************************************************************************/ |
ninBaud( baudrate ) |
char *baudrate; /* Desired baud rate, as a string of ASCII decimal |
* digits. |
*/ |
{ |
unsigned char msg[100]; |
|
tty_flush (nindy_serial); |
|
if (old_nindy) |
{ |
char *p; /* Pointer into buffer */ |
unsigned char csum; /* Calculated checksum */ |
|
/* Can't use putpkt() because after the baudrate change NINDY's |
ack/nak will look like gibberish. */ |
|
for (p=baudrate, csum=020+'z'; *p; p++) |
{ |
csum += *p; |
} |
sprintf (msg, "\020z%s#%02x", baudrate, csum); |
SERIAL_WRITE (nindy_serial, msg, strlen (msg)); |
} |
else |
{ |
/* Can't use "send" because NINDY reply will be unreadable after |
baud rate change. */ |
sprintf( msg, "z%s", baudrate ); |
putpkt( msg, strlen(msg)+1 ); /* "+1" to send terminator too */ |
} |
} |
|
/****************************************************************************** |
* ninBptDel: |
* Ask NINDY to delete the specified type of *hardware* breakpoint at |
* the specified address. If the 'addr' is -1, all breakpoints of |
* the specified type are deleted. |
***************************************************************************/ |
ninBptDel( addr, type ) |
long addr; /* Address in 960 memory */ |
char type; /* 'd' => data bkpt, 'i' => instruction breakpoint */ |
{ |
unsigned char buf[10]; |
|
if ( old_nindy ){ |
OninBptDel( addr, type == 'd' ? 1 : 0 ); |
return; |
} |
|
buf[0] = 'b'; |
buf[1] = type; |
|
if ( addr == -1 ){ |
send( buf, 2, NULL ); |
} else { |
store_unsigned_integer (&buf[2], 4, addr); |
send( buf, 6, NULL ); |
} |
} |
|
|
/****************************************************************************** |
* ninBptSet: |
* Ask NINDY to set the specified type of *hardware* breakpoint at |
* the specified address. |
******************************************************************************/ |
ninBptSet( addr, type ) |
long addr; /* Address in 960 memory */ |
char type; /* 'd' => data bkpt, 'i' => instruction breakpoint */ |
{ |
unsigned char buf[10]; |
|
if ( old_nindy ){ |
OninBptSet( addr, type == 'd' ? 1 : 0 ); |
return; |
} |
|
|
buf[0] = 'B'; |
buf[1] = type; |
store_unsigned_integer (&buf[2], 4, addr); |
send( buf, 6, NULL ); |
} |
|
|
/****************************************************************************** |
* ninConnect: |
* Open the specified tty. Get communications working at the specified |
* baud rate. Flush any pending I/O on the tty. |
* |
* Return the file descriptor, or -1 on failure. |
******************************************************************************/ |
int |
ninConnect( name, baudrate, brk, silent, old_protocol ) |
char *name; /* "/dev/ttyXX" to be opened */ |
char *baudrate;/* baud rate: a string of ascii decimal digits (eg,"9600")*/ |
int brk; /* 1 => send break to tty first thing after opening it*/ |
int silent; /* 1 => stifle unnecessary messages when talking to |
* this tty. |
*/ |
int old_protocol; |
{ |
int i; |
char *p; |
struct baudrate *brp; |
|
/* We will try each of the following paths when trying to open the tty |
*/ |
static char *prefix[] = { "", "/dev/", "/dev/tty", NULL }; |
|
if ( old_protocol ){ |
old_nindy = 1; |
} |
|
quiet = silent; /* Make global to this file */ |
|
for ( i=0; prefix[i] != NULL; i++ ){ |
p = xmalloc(strlen(prefix[i]) + strlen(name) + 1 ); |
strcpy( p, prefix[i] ); |
strcat( p, name ); |
nindy_serial = SERIAL_OPEN (p); |
if (nindy_serial != NULL) { |
#ifdef TIOCEXCL |
/* Exclusive use mode (hp9000 does not support it) */ |
ioctl(nindy_serial->fd,TIOCEXCL,NULL); |
#endif |
SERIAL_RAW (nindy_serial); |
|
if (brk) |
{ |
SERIAL_SEND_BREAK (nindy_serial); |
} |
|
brp = parse_baudrate( baudrate ); |
if ( brp == NULL ){ |
say("Illegal baudrate %s ignored; using 9600\n", |
baudrate); |
brp = parse_baudrate( "9600" ); |
} |
|
if ( !try_baudrate(nindy_serial, brp) ){ |
autobaud(nindy_serial, brp); |
} |
tty_flush (nindy_serial); |
say( "Connected to %s\n", p ); |
free(p); |
break; |
} |
free(p); |
} |
return 0; |
} |
|
#if 0 |
|
/* Currently unused; shouldn't we be doing this on target_kill and |
perhaps target_mourn? FIXME. */ |
|
/****************************************************************************** |
* ninGdbExit: |
* Ask NINDY to leave GDB mode and print a NINDY prompt. |
****************************************************************************/ |
ninGdbExit() |
{ |
if ( old_nindy ){ |
OninGdbExit(); |
return; |
} |
putpkt((unsigned char *) "E", 1 ); |
} |
#endif |
|
/****************************************************************************** |
* ninGo: |
* Ask NINDY to start or continue execution of an application program |
* in it's memory at the current ip. |
******************************************************************************/ |
ninGo( step_flag ) |
int step_flag; /* 1 => run in single-step mode */ |
{ |
if ( old_nindy ){ |
OninGo( step_flag ); |
return; |
} |
putpkt((unsigned char *) (step_flag ? "s" : "c"), 1 ); |
} |
|
|
/****************************************************************************** |
* ninMemGet: |
* Read a string of bytes from NINDY's address space (960 memory). |
******************************************************************************/ |
int |
ninMemGet(ninaddr, hostaddr, len) |
long ninaddr; /* Source address, in the 960 memory space */ |
unsigned char *hostaddr; /* Destination address, in our memory space */ |
int len; /* Number of bytes to read */ |
{ |
unsigned char buf[BUFSIZE+20]; |
int cnt; /* Number of bytes in next transfer */ |
int origlen = len; |
|
if ( old_nindy ){ |
OninMemGet(ninaddr, hostaddr, len); |
return; |
} |
|
for ( ; len > 0; len -= BUFSIZE ){ |
cnt = len > BUFSIZE ? BUFSIZE : len; |
|
buf[0] = 'm'; |
store_unsigned_integer (&buf[1], 4, ninaddr); |
buf[5] = cnt & 0xff; |
buf[6] = (cnt>>8) & 0xff; |
|
send( buf, 7, hostaddr ); |
|
ninaddr += cnt; |
hostaddr += cnt; |
} |
return origlen; |
} |
|
|
/****************************************************************************** |
* ninMemPut: |
* Write a string of bytes into NINDY's address space (960 memory). |
******************************************************************************/ |
int |
ninMemPut( ninaddr, hostaddr, len ) |
long ninaddr; /* Destination address, in NINDY memory space */ |
unsigned char *hostaddr; /* Source address, in our memory space */ |
int len; /* Number of bytes to write */ |
{ |
unsigned char buf[BUFSIZE+20]; |
int cnt; /* Number of bytes in next transfer */ |
int origlen = len; |
|
if ( old_nindy ){ |
OninMemPut( ninaddr, hostaddr, len ); |
return; |
} |
for ( ; len > 0; len -= BUFSIZE ){ |
cnt = len > BUFSIZE ? BUFSIZE : len; |
|
buf[0] = 'M'; |
store_unsigned_integer (&buf[1], 4, ninaddr); |
memcpy(buf + 5, hostaddr, cnt); |
send( buf, cnt+5, NULL ); |
|
ninaddr += cnt; |
hostaddr += cnt; |
} |
return origlen; |
} |
|
/****************************************************************************** |
* ninRegGet: |
* Retrieve the contents of a 960 register, and return them as a long |
* in host byte order. |
* |
* THIS ROUTINE CAN ONLY BE USED TO READ THE LOCAL, GLOBAL, AND |
* ip/ac/pc/tc REGISTERS. |
* |
******************************************************************************/ |
long |
ninRegGet( regname ) |
char *regname; /* Register name recognized by NINDY, subject to the |
* above limitations. |
*/ |
{ |
unsigned char outbuf[10]; |
unsigned char inbuf[20]; |
|
if ( old_nindy ){ |
return OninRegGet( regname ); |
} |
|
sprintf( outbuf, "u%s:", regname ); |
send( outbuf, strlen(outbuf), inbuf ); |
return extract_unsigned_integer (inbuf, 4); |
} |
|
/****************************************************************************** |
* ninRegPut: |
* Set the contents of a 960 register. |
* |
* THIS ROUTINE CAN ONLY BE USED TO SET THE LOCAL, GLOBAL, AND |
* ip/ac/pc/tc REGISTERS. |
* |
******************************************************************************/ |
ninRegPut( regname, val ) |
char *regname; /* Register name recognized by NINDY, subject to the |
* above limitations. |
*/ |
long val; /* New contents of register, in host byte-order */ |
{ |
unsigned char buf[20]; |
int len; |
|
if ( old_nindy ){ |
OninRegPut( regname, val ); |
return; |
} |
|
sprintf( buf, "U%s:", regname ); |
len = strlen(buf); |
store_unsigned_integer (&buf[len], 4, val); |
send( buf, len+4, NULL ); |
} |
|
/****************************************************************************** |
* ninRegsGet: |
* Get a dump of the contents of the entire 960 register set. The |
* individual registers appear in the dump in the following order: |
* |
* pfp sp rip r3 r4 r5 r6 r7 |
* r8 r9 r10 r11 r12 r13 r14 r15 |
* g0 g1 g2 g3 g4 g5 g6 g7 |
* g8 g9 g10 g11 g12 g13 g14 fp |
* pc ac ip tc fp0 fp1 fp2 fp3 |
* |
* Each individual register comprises exactly 4 bytes, except for |
* fp0-fp3, which are 8 bytes. All register values are in 960 |
* (little-endian) byte order. |
* |
******************************************************************************/ |
ninRegsGet( regp ) |
unsigned char *regp; /* Where to place the register dump */ |
{ |
if ( old_nindy ){ |
OninRegsGet( regp ); |
return; |
} |
send( (unsigned char *) "r", 1, regp ); |
} |
|
|
/****************************************************************************** |
* ninRegsPut: |
* Initialize the entire 960 register set to a specified set of values. |
* The format of the register value data should be the same as that |
* returned by ninRegsGet. |
* |
* WARNING: |
* All register values must be in 960 (little-endian) byte order. |
* |
******************************************************************************/ |
ninRegsPut( regp ) |
char *regp; /* Pointer to desired values of registers */ |
{ |
/* Number of bytes that we send to nindy. I believe this is defined by |
the protocol (it does not agree with REGISTER_BYTES). */ |
#define NINDY_REGISTER_BYTES ((36*4) + (4*8)) |
unsigned char buf[NINDY_REGISTER_BYTES+10]; |
|
if ( old_nindy ){ |
OninRegsPut( regp ); |
return; |
} |
|
buf[0] = 'R'; |
memcpy(buf+1, regp, NINDY_REGISTER_BYTES ); |
send( buf, NINDY_REGISTER_BYTES+1, NULL ); |
} |
|
|
/****************************************************************************** |
* ninReset: |
* Ask NINDY to perform a soft reset; wait for the reset to complete. |
* |
******************************************************************************/ |
ninReset() |
{ |
unsigned char ack; |
|
if ( old_nindy ){ |
OninReset(); |
return; |
} |
|
while (1){ |
putpkt((unsigned char *) "X", 1 ); |
while (1){ |
if ( !rdnin(&ack,1,5) ){ |
/* Timed out */ |
break; /* Resend */ |
} |
if ( ack == '+' ){ |
return; |
} |
} |
} |
} |
|
|
/****************************************************************************** |
* ninSrq: |
* Assume NINDY has stopped execution of the 960 application program in |
* order to process a host service request (srq). Ask NINDY for the |
* srq arguments, perform the requested service, and send an "srq |
* complete" message so NINDY will return control to the application. |
* |
******************************************************************************/ |
ninSrq() |
{ |
/* FIXME: Imposes arbitrary limits on lengths of pathnames and such. */ |
unsigned char buf[BUFSIZE]; |
int retcode; |
unsigned char srqnum; |
int i; |
int offset; |
int arg[MAX_SRQ_ARGS]; |
|
if ( old_nindy ){ |
OninSrq(); |
return; |
} |
|
|
/* Get srq number and arguments |
*/ |
send((unsigned char *) "!", 1, buf ); |
|
srqnum = buf[0]; |
for ( i=0, offset=1; i < MAX_SRQ_ARGS; i++, offset+=4 ){ |
arg[i] = extract_unsigned_integer (&buf[offset], 4); |
} |
|
/* Process Srq |
*/ |
switch( srqnum ){ |
case BS_CLOSE: |
/* args: file descriptor */ |
if ( arg[0] > 2 ){ |
retcode = close( arg[0] ); |
} else { |
retcode = 0; |
} |
break; |
case BS_CREAT: |
/* args: filename, mode */ |
ninStrGet( arg[0], buf ); |
retcode = creat(buf,arg[1]); |
break; |
case BS_OPEN: |
/* args: filename, flags, mode */ |
ninStrGet( arg[0], buf ); |
retcode = open(buf,arg[1],arg[2]); |
break; |
case BS_READ: |
/* args: file descriptor, buffer, count */ |
retcode = read(arg[0],buf,arg[2]); |
if ( retcode > 0 ){ |
ninMemPut( arg[1], buf, retcode ); |
} |
break; |
case BS_SEEK: |
/* args: file descriptor, offset, whence */ |
retcode = lseek(arg[0],arg[1],arg[2]); |
break; |
case BS_WRITE: |
/* args: file descriptor, buffer, count */ |
ninMemGet( arg[1], buf, arg[2] ); |
retcode = write(arg[0],buf,arg[2]); |
break; |
default: |
retcode = -1; |
break; |
} |
|
/* Send request termination status to NINDY |
*/ |
buf[0] = 'e'; |
store_unsigned_integer (&buf[1], 4, retcode); |
send( buf, 5, NULL ); |
} |
|
|
/****************************************************************************** |
* ninStopWhy: |
* Assume the application program has stopped (i.e., a DLE was received |
* from NINDY). Ask NINDY for status information describing the |
* reason for the halt. |
* |
* Returns a non-zero value if the user program has exited, 0 otherwise. |
* Also returns the following information, through passed pointers: |
* - why: an exit code if program the exited; otherwise the reason |
* why the program halted (see stop.h for values). |
* - contents of register ip (little-endian byte order) |
* - contents of register sp (little-endian byte order) |
* - contents of register fp (little-endian byte order) |
******************************************************************************/ |
char |
ninStopWhy( whyp, ipp, fpp, spp ) |
unsigned char *whyp; /* Return the 'why' code through this pointer */ |
long *ipp; /* Return contents of register ip through this pointer */ |
long *fpp; /* Return contents of register fp through this pointer */ |
long *spp; /* Return contents of register sp through this pointer */ |
{ |
unsigned char buf[30]; |
extern char OninStopWhy (); |
|
if ( old_nindy ){ |
return OninStopWhy( whyp, ipp, fpp, spp ); |
} |
send((unsigned char *) "?", 1, buf ); |
|
*whyp = buf[1]; |
memcpy ((char *)ipp, &buf[2], sizeof (*ipp)); |
memcpy ((char *)fpp, &buf[6], sizeof (*ipp)); |
memcpy ((char *)spp, &buf[10], sizeof (*ipp)); |
return buf[0]; |
} |
|
/****************************************************************************** |
* ninStrGet: |
* Read a '\0'-terminated string of data out of the 960 memory space. |
* |
******************************************************************************/ |
static |
ninStrGet( ninaddr, hostaddr ) |
unsigned long ninaddr; /* Address of string in NINDY memory space */ |
unsigned char *hostaddr; /* Address of the buffer to which string should |
* be copied. |
*/ |
{ |
unsigned char cmd[5]; |
|
cmd[0] = '"'; |
store_unsigned_integer (&cmd[1], 4, ninaddr); |
send( cmd, 5, hostaddr ); |
} |
|
#if 0 |
/* Not used. */ |
|
/****************************************************************************** |
* ninVersion: |
* Ask NINDY for version information about itself. |
* The information is sent as an ascii string in the form "x.xx,<arch>", |
* where, |
* x.xx is the version number |
* <arch> is the processor architecture: "KA", "KB", "MC", "CA" * |
* |
******************************************************************************/ |
int |
ninVersion( p ) |
unsigned char *p; /* Where to place version string */ |
{ |
|
if ( old_nindy ){ |
return OninVersion( p ); |
} |
send((unsigned char *) "v", 1, p ); |
return strlen(p); |
} |
#endif /* 0 */ |
/coff.h
0,0 → 1,336
/* Copyright 1990, 1992 Free Software Foundation, Inc. |
* |
* This code was donated by Intel Corp. |
* |
* This is a coff version of a.out.h to support 80960 debugging from |
* a Unix (possibly BSD) host. It's used by: |
* o gdb960 to symbols in code generated with Intel (non-GNU) tools. |
* o comm960 to convert a b.out file to a coff file for download. |
*/ |
|
|
/********************** FILE HEADER **********************/ |
|
struct filehdr { |
unsigned short f_magic; /* magic number */ |
unsigned short f_nscns; /* number of sections */ |
long f_timdat; /* time & date stamp */ |
long f_symptr; /* file pointer to symtab */ |
long f_nsyms; /* number of symtab entries */ |
unsigned short f_opthdr; /* sizeof(optional hdr) */ |
unsigned short f_flags; /* flags */ |
}; |
|
|
/* Bits for f_flags: |
* F_RELFLG relocation info stripped from file |
* F_EXEC file is executable (no unresolved externel references) |
* F_LNNO line nunbers stripped from file |
* F_LSYMS local symbols stripped from file |
* F_AR32WR file has byte ordering of an AR32WR machine (e.g. vax) |
*/ |
#define F_RELFLG 0000001 |
#define F_EXEC 0000002 |
#define F_LNNO 0000004 |
#define F_LSYMS 0000010 |
#define F_AR32WR 0000400 |
|
|
/* |
* Intel 80960 (I960) processor flags. |
* F_I960TYPE == mask for processor type field. |
*/ |
#define F_I960TYPE 0170000 |
#define F_I960CA 0010000 |
#define F_I960FLOAT 0020000 |
#define F_I960BA 0030000 |
#define F_I960XA 0040000 |
|
/* |
* i80960 Magic Numbers |
*/ |
#define I960ROMAGIC 0540 /* read-only text segments */ |
#define I960RWMAGIC 0541 /* read-write text segments */ |
|
#define I960BADMAG(x) (((x).f_magic!=I960ROMAGIC) && ((x).f_magic!=I960RWMAGIC)) |
|
#define FILHDR struct filehdr |
#define FILHSZ sizeof(FILHDR) |
|
|
/********************** AOUT "OPTIONAL HEADER" **********************/ |
|
typedef struct { |
unsigned long phys_addr; |
unsigned long bitarray; |
} TAGBITS; |
|
typedef struct aouthdr { |
short magic; /* type of file */ |
short vstamp; /* version stamp */ |
unsigned long tsize; /* text size in bytes, padded to FW bdry*/ |
unsigned long dsize; /* initialized data " " */ |
unsigned long bsize; /* uninitialized data " " */ |
#if U3B |
unsigned long dum1; |
unsigned long dum2; /* pad to entry point */ |
#endif |
unsigned long entry; /* entry pt. */ |
unsigned long text_start; /* base of text used for this file */ |
unsigned long data_start; /* base of data used for this file */ |
unsigned long tagentries; /* number of tag entries to follow */ |
} AOUTHDR; |
|
/* return a pointer to the tag bits array */ |
|
#define TAGPTR(aout) ((TAGBITS *) (&(aout.tagentries)+1)) |
|
/* compute size of a header */ |
|
#define AOUTSZ(aout) (sizeof(AOUTHDR)+(aout.tagentries*sizeof(TAGBITS))) |
|
/********************** STORAGE CLASSES **********************/ |
|
#define C_EFCN -1 /* physical end of function */ |
#define C_NULL 0 |
#define C_AUTO 1 /* automatic variable */ |
#define C_EXT 2 /* external symbol */ |
#define C_STAT 3 /* static */ |
#define C_REG 4 /* register variable */ |
#define C_EXTDEF 5 /* external definition */ |
#define C_LABEL 6 /* label */ |
#define C_ULABEL 7 /* undefined label */ |
#define C_MOS 8 /* member of structure */ |
#define C_ARG 9 /* function argument */ |
#define C_STRTAG 10 /* structure tag */ |
#define C_MOU 11 /* member of union */ |
#define C_UNTAG 12 /* union tag */ |
#define C_TPDEF 13 /* type definition */ |
#define C_USTATIC 14 /* undefined static */ |
#define C_ENTAG 15 /* enumeration tag */ |
#define C_MOE 16 /* member of enumeration */ |
#define C_REGPARM 17 /* register parameter */ |
#define C_FIELD 18 /* bit field */ |
#define C_BLOCK 100 /* ".bb" or ".eb" */ |
#define C_FCN 101 /* ".bf" or ".ef" */ |
#define C_EOS 102 /* end of structure */ |
#define C_FILE 103 /* file name */ |
#define C_LINE 104 /* line # reformatted as symbol table entry */ |
#define C_ALIAS 105 /* duplicate tag */ |
#define C_HIDDEN 106 /* ext symbol in dmert public lib */ |
|
/* New storage classes for 80960 */ |
|
#define C_SCALL 107 /* Procedure reachable via system call */ |
#define C_LEAFPROC 108 /* Leaf procedure, "call" via BAL */ |
|
|
/********************** SECTION HEADER **********************/ |
|
struct scnhdr { |
char s_name[8]; /* section name */ |
long s_paddr; /* physical address, aliased s_nlib */ |
long s_vaddr; /* virtual address */ |
long s_size; /* section size */ |
long s_scnptr; /* file ptr to raw data for section */ |
long s_relptr; /* file ptr to relocation */ |
long s_lnnoptr; /* file ptr to line numbers */ |
unsigned short s_nreloc; /* number of relocation entries */ |
unsigned short s_nlnno; /* number of line number entries*/ |
long s_flags; /* flags */ |
unsigned long s_align; /* section alignment */ |
}; |
|
/* |
* names of "special" sections |
*/ |
#define _TEXT ".text" |
#define _DATA ".data" |
#define _BSS ".bss" |
|
/* |
* s_flags "type" |
*/ |
#define STYP_TEXT 0x20 /* section contains text only */ |
#define STYP_DATA 0x40 /* section contains data only */ |
#define STYP_BSS 0x80 /* section contains bss only */ |
|
#define SCNHDR struct scnhdr |
#define SCNHSZ sizeof(SCNHDR) |
|
|
/********************** LINE NUMBERS **********************/ |
|
/* 1 line number entry for every "breakpointable" source line in a section. |
* Line numbers are grouped on a per function basis; first entry in a function |
* grouping will have l_lnno = 0 and in place of physical address will be the |
* symbol table index of the function name. |
*/ |
struct lineno{ |
union { |
long l_symndx; /* function name symbol index, iff l_lnno == 0*/ |
long l_paddr; /* (physical) address of line number */ |
} l_addr; |
unsigned short l_lnno; /* line number */ |
char padding[2]; /* force alignment */ |
}; |
|
#define LINENO struct lineno |
#define LINESZ sizeof(LINENO) |
|
|
/********************** SYMBOLS **********************/ |
|
#define SYMNMLEN 8 /* # characters in a symbol name */ |
#define FILNMLEN 14 /* # characters in a file name */ |
#define DIMNUM 4 /* # array dimensions in auxiliary entry */ |
|
|
struct syment { |
union { |
char _n_name[SYMNMLEN]; /* old COFF version */ |
struct { |
long _n_zeroes; /* new == 0 */ |
long _n_offset; /* offset into string table */ |
} _n_n; |
char *_n_nptr[2]; /* allows for overlaying */ |
} _n; |
long n_value; /* value of symbol */ |
short n_scnum; /* section number */ |
char pad1[2]; /* force alignment */ |
unsigned long n_type; /* type and derived type */ |
char n_sclass; /* storage class */ |
char n_numaux; /* number of aux. entries */ |
char pad2[2]; /* force alignment */ |
}; |
|
#define n_name _n._n_name |
#define n_zeroes _n._n_n._n_zeroes |
#define n_offset _n._n_n._n_offset |
|
/* |
* Relocatable symbols have number of the section in which they are defined, |
* or one of the following: |
*/ |
#define N_UNDEF 0 /* undefined symbol */ |
#define N_ABS -1 /* value of symbol is absolute */ |
#define N_DEBUG -2 /* debugging symbol -- symbol value is meaningless */ |
|
/* |
* Type of a symbol, in low 4 bits of the word |
*/ |
#define T_NULL 0 |
#define T_VOID 1 /* function argument (only used by compiler) */ |
#define T_CHAR 2 /* character */ |
#define T_SHORT 3 /* short integer */ |
#define T_INT 4 /* integer */ |
#define T_LONG 5 /* long integer */ |
#define T_FLOAT 6 /* floating point */ |
#define T_DOUBLE 7 /* double word */ |
#define T_STRUCT 8 /* structure */ |
#define T_UNION 9 /* union */ |
#define T_ENUM 10 /* enumeration */ |
#define T_MOE 11 /* member of enumeration*/ |
#define T_UCHAR 12 /* unsigned character */ |
#define T_USHORT 13 /* unsigned short */ |
#define T_UINT 14 /* unsigned integer */ |
#define T_ULONG 15 /* unsigned long */ |
#define T_LNGDBL 16 /* long double */ |
|
|
/* |
* derived types |
*/ |
#define DT_PTR 1 /* pointer */ |
#define DT_FCN 2 /* function */ |
#define DT_ARY 3 /* array */ |
|
#define N_BTMASK 037 |
#define N_TMASK 0140 |
#define N_BTSHFT 5 |
#define N_TSHIFT 2 |
|
#define BTYPE(x) ((x) & N_BTMASK) |
|
|
#define ISPTR(x) (((x) & N_TMASK) == (DT_PTR << N_BTSHFT)) |
#define ISFCN(x) (((x) & N_TMASK) == (DT_FCN << N_BTSHFT)) |
#define ISARY(x) (((x) & N_TMASK) == (DT_ARY << N_BTSHFT)) |
|
#define DECREF(x) ((((x)>>N_TSHIFT)&~N_BTMASK)|((x)&N_BTMASK)) |
|
union auxent { |
struct { |
long x_tagndx; /* str, un, or enum tag indx */ |
union { |
struct { |
unsigned short x_lnno; /* declaration line number */ |
unsigned short x_size; /* str/union/array size */ |
} x_lnsz; |
long x_fsize; /* size of function */ |
} x_misc; |
union { |
struct { /* if ISFCN, tag, or .bb */ |
long x_lnnoptr; /* ptr to fcn line # */ |
long x_endndx; /* entry ndx past block end */ |
} x_fcn; |
struct { /* if ISARY, up to 4 dimen. */ |
unsigned short x_dimen[DIMNUM]; |
} x_ary; |
} x_fcnary; |
unsigned short x_tvndx; /* tv index */ |
} x_sym; |
|
union { |
char x_fname[FILNMLEN]; |
struct { |
long x_zeroes; |
long x_offset; |
} x_n; |
} x_file; |
|
struct { |
long x_scnlen; /* section length */ |
unsigned short x_nreloc; /* # relocation entries */ |
unsigned short x_nlinno; /* # line numbers */ |
} x_scn; |
|
struct { |
long x_stdindx; |
} x_sc; |
|
struct { |
unsigned long x_balntry; |
} x_bal; |
|
char a[sizeof(struct syment)]; /* force auxent/syment sizes to match */ |
}; |
|
#define SYMENT struct syment |
#define SYMESZ sizeof(SYMENT) |
#define AUXENT union auxent |
#define AUXESZ sizeof(AUXENT) |
|
#if VAX || I960 |
# define _ETEXT "_etext" |
#else |
# define _ETEXT "etext" |
#endif |
|
/********************** RELOCATION DIRECTIVES **********************/ |
|
struct reloc { |
long r_vaddr; /* Virtual address of reference */ |
long r_symndx; /* Index into symbol table */ |
unsigned short r_type; /* Relocation type */ |
char pad[2]; /* Unused */ |
}; |
|
/* Only values of r_type GNU/960 cares about */ |
#define R_RELLONG 17 /* Direct 32-bit relocation */ |
#define R_IPRMED 25 /* 24-bit ip-relative relocation */ |
#define R_OPTCALL 27 /* 32-bit optimizable call (leafproc/sysproc) */ |
|
|
#define RELOC struct reloc |
#define RELSZ sizeof(RELOC) |
/ttyflush.c
0,0 → 1,53
/* This file is part of GDB. |
|
This program is free software; you can redistribute it and/or modify |
it under the terms of the GNU General Public License as published by |
the Free Software Foundation; either version 2 of the License, or |
(at your option) any later version. |
|
This program is distributed in the hope that it will be useful, |
but WITHOUT ANY WARRANTY; without even the implied warranty of |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
GNU General Public License for more details. |
|
You should have received a copy of the GNU General Public License |
along with this program; if not, write to the Free Software |
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|
/* This started out life as code shared between the nindy monitor and |
GDB. For various reasons, this is no longer true. Eventually, it |
probably should be merged into remote-nindy.c. */ |
|
#include <stdio.h> |
#include "defs.h" |
#include "serial.h" |
|
#ifdef _MSC_VER |
# include <stdlib.h> |
# define sleep _sleep |
#endif |
|
/* Flush all pending input and output for SERIAL, wait for a second, and |
then if there is a character pending, discard it and flush again. */ |
|
int |
tty_flush (serial) |
serial_t serial; |
{ |
while (1) |
{ |
SERIAL_FLUSH_INPUT (serial); |
SERIAL_FLUSH_OUTPUT (serial); |
sleep(1); |
switch (SERIAL_READCHAR (serial, 0)) |
{ |
case SERIAL_TIMEOUT: |
case SERIAL_ERROR: |
case SERIAL_EOF: |
return 0; |
default: |
/* We read something. Eeek. Try again. */ |
break; |
} |
} |
} |
/VERSION
0,0 → 1,53
1.2 |
/block_io.h
0,0 → 1,68
/****************************************************************** |
Copyright 1990, 1992 Free Software Foundation, Inc. |
|
This code was donated by Intel Corp. |
|
Intel hereby grants you permission to copy, modify, and |
distribute this software and its documentation. Intel grants |
this permission provided that the above copyright notice |
appears in all copies and that both the copyright notice and |
this permission notice appear in supporting documentation. In |
addition, Intel grants this permission provided that you |
prominently mark as not part of the original any modifications |
made to this software or documentation, and that the name of |
Intel Corporation not be used in advertising or publicity |
pertaining to distribution of the software or the documentation |
without specific, written prior permission. |
|
Intel Corporation does not warrant, guarantee or make any |
representations regarding the use of, or the results of the use |
of, the software and documentation in terms of correctness, |
accuracy, reliability, currentness, or otherwise; and you rely |
on the software, documentation and results solely at your own |
risk. */ |
/******************************************************************/ |
|
/***************************************************************************** |
* Structures and definitions supporting NINDY requests for services by a |
* remote host. Used by NINDY monitor, library libnin, comm960, gdb960, |
* etc. Also contains some defines for NINDY console I/O requests. |
*****************************************************************************/ |
|
/* the following four are hardware dependent */ |
#define BIT_16 short |
#define BIT_32 int |
#define UBIT_16 unsigned short |
#define UBIT_32 unsigned int |
|
/* Service request numbers -- these are the services that can be asked of the |
* host. |
*/ |
#define BS_ACCESS 0x10 |
#define BS_CLOSE 0x20 |
#define BS_CREAT 0x30 |
#define BS_SEEK 0x40 |
#define BS_OPEN 0x50 |
#define BS_READ 0x60 |
#define BS_STAT 0x70 |
#define BS_SYSTEMD 0x80 |
#define BS_TIME 0x90 |
#define BS_UNMASK 0xa0 |
#define BS_UNLINK 0xb0 |
#define BS_WRITE 0xc0 |
|
|
/* Maximum number of arguments to any of the above service requests |
* (in addition to the request number). |
*/ |
#define MAX_SRQ_ARGS 3 |
|
/* Number of bytes of data that can be read or written by a single I/O request |
*/ |
#define BUFSIZE 1024 |
|
/* NINDY console I/O requests: CO sends a single character to stdout, |
* CI reads one. |
*/ |
#define CI 0 |
#define CO 1 |
/stop.h
0,0 → 1,86
/****************************************************************** |
Copyright 1990, 1992 Free Software Foundation, Inc. |
|
This code was donated by Intel Corp. |
|
Intel hereby grants you permission to copy, modify, and |
distribute this software and its documentation. Intel grants |
this permission provided that the above copyright notice |
appears in all copies and that both the copyright notice and |
this permission notice appear in supporting documentation. In |
addition, Intel grants this permission provided that you |
prominently mark as not part of the original any modifications |
made to this software or documentation, and that the name of |
Intel Corporation not be used in advertising or publicity |
pertaining to distribution of the software or the documentation |
without specific, written prior permission. |
|
Intel Corporation does not warrant, guarantee or make any |
representations regarding the use of, or the results of the use |
of, the software and documentation in terms of correctness, |
accuracy, reliability, currentness, or otherwise; and you rely |
on the software, documentation and results solely at your own |
risk. */ |
/******************************************************************/ |
|
|
/****************************************************************** |
* |
* REASONS WHY NINDY CAN STOP EXECUTING AN APPLICATION PROGRAM |
* |
* When NINDY stops executing an application program that was running |
* under remote host ("gdb") control, it signals the host by sending |
* a single ^P. The host can then query as to the reason for the halt. |
* NINDY responds with two bytes of information. |
* |
* The first byte is a boolean flag that indicates whether or not |
* the application has exited. |
* |
* If the flag is true, the second byte contains the exit code. |
* |
* If the flag is false, the second byte contains a "reason for |
* stopping" code. This file defines the possible values of that |
* code. |
* |
* There are three categories of reasons why the halt may have occurred: |
* faults, traces, and software interactions. The first two categories |
* are processor-dependent; the values of these codes are tightly coupled |
* to the hardware and should not be changed without first examining |
* src/nindy/common/fault.c. The software interactions involve |
* communication between NINDY and the host debugger; their codes are |
* arbitrary. |
* |
******************************************************************/ |
|
#define FAULT_PARALLEL 0x00 |
#define FAULT_UNKNOWN 0x01 |
#define FAULT_OPERATION 0x02 |
#define FAULT_ARITH 0x03 |
#define FAULT_FP 0x04 |
#define FAULT_CONSTR 0x05 |
#define FAULT_VM 0x06 |
#define FAULT_PROTECT 0x07 |
#define FAULT_MACHINE 0x08 |
#define FAULT_STRUCT 0x09 |
#define FAULT_TYPE 0x0a |
/* 0x0b reserved */ |
#define FAULT_PROCESS 0x0c |
#define FAULT_DESC 0x0d |
#define FAULT_EVENT 0x0e |
/* 0x0f reserved */ |
|
#define LAST_FAULT 0x0f |
|
#define TRACE_STEP 0x10 |
#define TRACE_BRANCH 0x11 |
#define TRACE_CALL 0x12 |
#define TRACE_RET 0x13 |
#define TRACE_PRERET 0x14 |
#define TRACE_SVC 0x15 |
#define TRACE_BKPT 0x16 |
|
#define STOP_SRQ 0xfe |
/* Application program has service request to make of host */ |
|
#define STOP_GDB_BPT 0xff |
/* Application program has reached breakpoint (fmark) set by host */ |
/Makefile
0,0 → 1,117
#Copyright 1992 Free Software Foundation, Inc. |
|
# This file is part of GDB. |
|
# This program is free software; you can redistribute it and/or modify |
# it under the terms of the GNU General Public License as published by |
# the Free Software Foundation; either version 2 of the License, or |
# (at your option) any later version. |
# |
# This program is distributed in the hope that it will be useful, |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# GNU General Public License for more details. |
# |
# You should have received a copy of the GNU General Public License |
# along with this program; if not, write to the Free Software |
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
#----------------------------------------------------------------------------- |
# Makefile for toolib.a -- host code shAred by more than one tool |
#----------------------------------------------------------------------------- |
|
RANLIB = ranlib |
|
# The following lines should be uncommented for system V (i386v). |
#__i386v__#USG = -DUSG |
#__i386v__#SYSV_INCL = ${IPATH}/sysv.h |
#__i386v__#RANLIB = echo >/dev/null |
|
# The following line should be uncommented for HP-UX |
#__hp9000__#USG = -DUSG |
#__hp9000__#SYSV_INCL = ${IPATH}/sysv.h |
#__hp9000__#RANLIB = echo >/dev/null |
|
# Essential under System V, harmless elsewhere |
SHELL = /bin/sh |
|
#'HOST' will be defined in the host-specific makefile by 'make make' |
|
TARG = toolib.a |
OPT = -g |
IPATH = ../../include |
CFLAGS = ${OPT} ${USG} -I${IPATH} -DHOST=\"${HOST}\" |
OBJS = coffstrip.o nindy.o ttybreak.o ttyflush.o Onindy.o |
|
${TARG}: ${OBJS} VERSION |
make ver960.o |
rm -f ${TARG} |
ar cvr ${TARG} ${OBJS} ver960.o |
${RANLIB} ${TARG} |
|
coffstrip.o: ${IPATH}/b.out.h ${IPATH}/coff.h ${IPATH}/sysv.h |
nindy.o: ${IPATH}/block_io.h ${IPATH}/env.h ${IPATH}/sysv.h |
nindy.o: ${IPATH}/ttycntl.h ${IPATH}/wait.h |
ttybreak.o: ${IPATH}/ttycntl.h |
ttyflush.o: ${IPATH}/ttycntl.h |
Onindy.o: ${IPATH}/block_io.h ${IPATH}/env.h ${IPATH}/sysv.h |
Onindy.o: ${IPATH}/ttycntl.h ${IPATH}/wait.h |
|
|
#----------------------------------------------------------------------------- |
# 'STANDARD' GNU/960 TARGETS BELOW THIS POINT |
# |
# 'VERSION' file must be present and contain a string of the form "x.y" |
#----------------------------------------------------------------------------- |
|
ver960.c: FORCE |
rm -f ver960.c |
echo "char toolib_ver[]= \"${TARG} `cat VERSION`, `date`\";" > ver960.c |
|
|
# This target should be invoked before building a new release. |
# 'VERSION' file must be present and contain a string of the form "x.y" |
# |
roll: |
@V=`cat VERSION` ; \ |
MAJ=`sed 's/\..*//' VERSION` ; \ |
MIN=`sed 's/.*\.//' VERSION` ; \ |
V=$$MAJ.`expr $$MIN + 1` ; \ |
rm -f VERSION ; \ |
echo $$V >VERSION ; \ |
echo Version $$V |
|
# Dummy target to force execution of dependent targets. |
# |
FORCE: |
|
# 'G960BASE' will be defined at invocation |
# |
install: |
make ${TARG} |
mv -f ${TARG} ${G960BASE}/lib |
|
clean: |
rm -f ${TARG} *.o core |
|
# Target to uncomment host-specific lines in this makefile. Such lines must |
# have the following string beginning in column 1: #__<hostname>__# |
# Original Makefile is backed up as 'Makefile.old'. |
# |
# Invoke with: make make HOST=xxx |
# |
make: |
-@if test $(HOST)x = x ; then \ |
echo 'Specify "make make HOST=???"'; \ |
exit 1; \ |
fi ; \ |
grep -s "^#The next line was generated by 'make make'" Makefile; \ |
if test $$? = 0 ; then \ |
echo "Makefile has already been processed with 'make make'";\ |
exit 1; \ |
fi ; \ |
mv -f Makefile Makefile.old; \ |
echo "#The next line was generated by 'make make'" >Makefile ; \ |
echo "HOST=$(HOST)" >>Makefile ; \ |
echo >>Makefile ; \ |
sed "s/^#__$(HOST)__#//" < Makefile.old >>Makefile |
/README
0,0 → 1,3
The files in this directory started out life as code shared between |
the nindy monitor and GDB. For various reasons, this is no longer |
true. Eventually, they probably should be merged into remote-nindy.c. |
/b.out.h
0,0 → 1,158
/* Copyright 1992 Free Software Foundation, Inc. |
* |
* This file is a modified version of 'a.out.h'. It is to be used in all |
* all GNU tools modified to support the i80960 (or tools that operate on |
* object files created by such tools). |
* |
* All i80960 development is done in a CROSS-DEVELOPMENT environment. I.e., |
* object code is generated on, and executed under the direction of a symbolic |
* debugger running on, a host system. We do not want to be subject to the |
* vagaries of which host it is or whether it supports COFF or a.out format, |
* or anything else. We DO want to: |
* |
* o always generate the same format object files, regardless of host. |
* |
* o have an 'a.out' header that we can modify for our own purposes |
* (the 80960 is typically an embedded processor and may require |
* enhanced linker support that the normal a.out.h header can't |
* accommodate). |
* |
* As for byte-ordering, the following rules apply: |
* |
* o Text and data that is actually downloaded to the target is always |
* in i80960 (little-endian) order. |
* |
* o All other numbers (in the header, symbols, relocation directives) |
* are in host byte-order: object files CANNOT be lifted from a |
* little-end host and used on a big-endian (or vice versa) without |
* modification. |
* |
* o The downloader ('comm960') takes care to generate a pseudo-header |
* with correct (i80960) byte-ordering before shipping text and data |
* off to the NINDY monitor in the target systems. Symbols and |
* relocation info are never sent to the target. |
*/ |
|
|
#define BMAGIC 0415 |
/* We don't accept the following (see N_BADMAG macro). |
* They're just here so GNU code will compile. |
*/ |
#define OMAGIC 0407 /* old impure format */ |
#define NMAGIC 0410 /* read-only text */ |
#define ZMAGIC 0413 /* demand load format */ |
|
/* FILE HEADER |
* All 'lengths' are given as a number of bytes. |
* All 'alignments' are for relinkable files only; an alignment of |
* 'n' indicates the corresponding segment must begin at an |
* address that is a multiple of (2**n). |
*/ |
struct exec { |
/* Standard stuff */ |
unsigned long a_magic; /* Identifies this as a b.out file */ |
unsigned long a_text; /* Length of text */ |
unsigned long a_data; /* Length of data */ |
unsigned long a_bss; /* Length of runtime uninitialized data area */ |
unsigned long a_syms; /* Length of symbol table */ |
unsigned long a_entry; /* Runtime start address */ |
unsigned long a_trsize; /* Length of text relocation info */ |
unsigned long a_drsize; /* Length of data relocation info */ |
|
/* Added for i960 */ |
unsigned long a_tload; /* Text runtime load address */ |
unsigned long a_dload; /* Data runtime load address */ |
unsigned char a_talign; /* Alignment of text segment */ |
unsigned char a_dalign; /* Alignment of data segment */ |
unsigned char a_balign; /* Alignment of bss segment */ |
unsigned char unused; /* (Just to make struct size a multiple of 4) */ |
}; |
|
#define N_BADMAG(x) (((x).a_magic)!=BMAGIC) |
#define N_TXTOFF(x) ( sizeof(struct exec) ) |
#define N_DATOFF(x) ( N_TXTOFF(x) + (x).a_text ) |
#define N_TROFF(x) ( N_DATOFF(x) + (x).a_data ) |
#define N_DROFF(x) ( N_TROFF(x) + (x).a_trsize ) |
#define N_SYMOFF(x) ( N_DROFF(x) + (x).a_drsize ) |
#define N_STROFF(x) ( N_SYMOFF(x) + (x).a_syms ) |
|
/* A single entry in the symbol table |
*/ |
struct nlist { |
union { |
char *n_name; |
struct nlist *n_next; |
long n_strx; /* Index into string table */ |
} n_un; |
unsigned char n_type; /* See below */ |
char n_other; /* Used in i80960 support -- see below */ |
short n_desc; |
unsigned long n_value; |
}; |
|
|
/* Legal values of n_type |
*/ |
#define N_UNDF 0 /* Undefined symbol */ |
#define N_ABS 2 /* Absolute symbol */ |
#define N_TEXT 4 /* Text symbol */ |
#define N_DATA 6 /* Data symbol */ |
#define N_BSS 8 /* BSS symbol */ |
#define N_FN 31 /* Filename symbol */ |
|
#define N_EXT 1 /* External symbol (OR'd in with one of above) */ |
#define N_TYPE 036 /* Mask for all the type bits */ |
#define N_STAB 0340 /* Mask for all bits used for SDB entries */ |
|
/* MEANING OF 'n_other' |
* |
* If non-zero, the 'n_other' fields indicates either a leaf procedure or |
* a system procedure, as follows: |
* |
* 1 <= n_other <= 32 : |
* The symbol is the entry point to a system procedure. |
* 'n_value' is the address of the entry, as for any other |
* procedure. The system procedure number (which can be used in |
* a 'calls' instruction) is (n_other-1). These entries come from |
* '.sysproc' directives. |
* |
* n_other == N_CALLNAME |
* the symbol is the 'call' entry point to a leaf procedure. |
* The *next* symbol in the symbol table must be the corresponding |
* 'bal' entry point to the procedure (see following). These |
* entries come from '.leafproc' directives in which two different |
* symbols are specified (the first one is represented here). |
* |
* |
* n_other == N_BALNAME |
* the symbol is the 'bal' entry point to a leaf procedure. |
* These entries result from '.leafproc' directives in which only |
* one symbol is specified, or in which the same symbol is |
* specified twice. |
* |
* Note that an N_CALLNAME entry *must* have a corresponding N_BALNAME entry, |
* but not every N_BALNAME entry must have an N_CALLNAME entry. |
*/ |
#define N_CALLNAME -1 |
#define N_BALNAME -2 |
|
|
struct relocation_info { |
int r_address; /* File address of item to be relocated */ |
unsigned |
r_symbolnum:24,/* Index of symbol on which relocation is based*/ |
r_pcrel:1, /* 1 => relocate PC-relative; else absolute |
* On i960, pc-relative implies 24-bit |
* address, absolute implies 32-bit. |
*/ |
r_length:2, /* Number of bytes to relocate: |
* 0 => 1 byte |
* 1 => 2 bytes |
* 2 => 4 bytes -- only value used for i960 |
*/ |
r_extern:1, |
r_bsr:1, /* Something for the GNU NS32K assembler */ |
r_disp:1, /* Something for the GNU NS32K assembler */ |
r_callj:1, /* 1 if relocation target is an i960 'callj' */ |
nuthin:1; /* Unused */ |
}; |
/env.h
0,0 → 1,12
/* Copyright 1990, 1992 Free Software Foundation, Inc. |
* |
* This code was donated by Intel Corp. |
* |
* GNU/960 tool runtime environment |
*/ |
|
|
/* Base directory at which GNU/960 tools are assumed to be installed, if |
* the environment variable G960BASE is not defined. |
*/ |
#define DEFAULT_BASE "/usr/local/g960" |