📄 nindy.c
字号:
/***************************************************************************** * 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. *****************************************************************************/static char rcsid[] = "Id: nindy.c,v 1.1.1.1 1991/03/28 16:20:57 rich Exp $";/****************************************************************************** * * NINDY INTERFACE ROUTINES * * The routines in this file define and implement an interface between code * (such as a high-level debugger) running on a remote host and the NINDY * ROM monitor on an i960 board. These routines are to be linked with * and called by the host code. * * These routines handle both the formatting/transferring of commands to NINDY * and the receipt/formatting of data returned in response to them. The * actual transfer protocol is hidden from the host programmer within them. * For a full description of the lowest level NINDY/host transfer protocol, * see the block header of the file gdb.c, in the NINDY source code. * * 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. * * WARNING: Changes made here should be tested in both gdb960 and comm960. * ******************************************************************************/#include <stdio.h>#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"#include "block_io.h"#include "wait.h"#include "env.h"#ifdef USG# include <unistd.h># include "sysv.h"#else /* BSD */# include "string.h"# include <sys/time.h>#endif#ifndef ERROR#define ERROR -1#endif#define DLE 0x10 /* ^P */#define XON 0x11 /* ^Q */#define XOFF 0x13 /* ^S */#define ESC 0x1b#define REGISTER_BYTES ((36*4) + (4*8))#define TIMEOUT -1extern char *malloc();extern void free();static int quiet = 0; /* 1 => stifle unnecessary messages */static int nindy_fd; /* File descriptor of tty connected to 960/NINDY board*/static int old_nindy = 0; /* 1 => use old (hex) communication protocol */static ninStrGet(); /**************************** * * * MISCELLANEOUS UTILTIES * * * ****************************/#if 0/****************************************************************************** * byteswap: * 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. * ******************************************************************************/staticlongbyteswap( 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;}#endif /****************************************************************************** * get_int: * Copy the little-endian integer pointed at by 'p' and return it in * the host byte order. 'p' may be an unaligned address, so do the copy * a byte at a time. ******************************************************************************/intget_int( p ) unsigned char *p;{ int n; int i; n = 0; p += sizeof(int) - 1; for ( i = 0; i < sizeof(n); i++ ){ n <<= 8; n |= *p--; } return n;}/****************************************************************************** * put_int: * Copy the integer 'n' (which is in host byte order) to the location * pointed at by 'p', leaving it in little-endian byte order. * 'p' may be an unaligned address, so do the move a byte at a time. ******************************************************************************/intput_int( p, n ) unsigned char *p; int n;{ int i; for ( i = 0; i < sizeof(n); i++ ){ *p++ = n; n >>= 8; }}/****************************************************************************** * 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. ******************************************************************************//* FIXME: use varargs for this. */staticsay( fmt, arg1, arg2 ) char *fmt; int arg1, arg2;{ if ( !quiet ){ printf( fmt, arg1, arg2 ); fflush( stdout ); }}/****************************************************************************** * 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). *****************************************************************************/staticchar *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 = malloc( 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 * * * *****************************//****************************************************************************** * timed_read: * Read up to 'n' characters (less if fewer are available) from the NINDY * tty. Wait up to 'timeout' seconds for something to arrive. Return * the number of characters read, 0 on timeout. ******************************************************************************/#ifdef USGstatic int saw_alarm;static voidalarm_handler(){ saw_alarm = 1;}staticinttimed_read(buf,n,timeout) unsigned char * buf; /* Where to put the read characters */ int n; /* Max number of characters to read */ int timeout; /* Timeout, in seconds */{ void (*old_alarm)(); /* Save alarm signal handler here on entry */ int cnt; old_alarm = signal( SIGALRM,alarm_handler ); saw_alarm = 0; alarm(timeout); do { cnt = n; TTY_NBREAD(nindy_fd,cnt,buf); } while ( (cnt <= 0) && !saw_alarm ); alarm(0); signal( SIGALRM,old_alarm ); return saw_alarm ? 0 : cnt;}#else /* BSD */staticinttimed_read(buf,n,timeout) unsigned char * buf; /* Where to put the read characters */ int n; /* Max number of characters to read */ int timeout; /* Timeout, in seconds */{ struct timeval t; fd_set f; t.tv_sec = (long) timeout; t.tv_usec= 0; FD_ZERO( &f ); FD_SET( nindy_fd, &f ); if ( select(nindy_fd+1,&f,0,0,&t) ){ return read( nindy_fd, buf, n ); } else { return 0; }}#endif/****************************************************************************** * rdnin: * Read *exactly* 'n' characters from the NINDY tty. 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. ******************************************************************************/staticintrdnin(buf,n,timeout) unsigned char * buf; /* Where to place characters read */ int n; /* Number of characters to read */ int timeout; /* Timeout, in seconds */{ static unsigned char *mybuf = NULL; /* Dynamically allocated local buffer */ static int mybuflen = 0; /* Current size of local buffer */ int escape_seen; /* 1 => last character of a read was an ESC */ int nread; /* Number of chars returned by timed_read() */ unsigned char c; int i; /* Make sure local buffer is big enough */ if ( n > mybuflen ){ if ( mybuf ){ free( mybuf ); } mybuf = (unsigned char *) malloc( mybuflen=n ); } /* More than one loop will be necessary if there are any * escape sequences in the input */ escape_seen = 0; while ( n ){ nread = timed_read(mybuf,n,timeout); if ( nread <= 0 ){ return 0; /* TIMED OUT */ } /* Copy characters from local buffer to caller's buffer, * converting escape sequences as they're encountered. */ for ( i = 0; i < nread; i++ ){ c = mybuf[i]; if ( escape_seen ){ escape_seen = 0; c &= ~0x40; } else if ( c == ESC ){ if ( ++i >= nread ){ /* Need to refill local buffer */ escape_seen = 1; break; } c = mybuf[i] & ~0x40; } *buf++ = c; n--; } } 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. ******************************************************************************/staticintgetpkt(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 ){ write (nindy_fd, "+", 1); return hdr[2]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -