📄 nindy.c
字号:
} free(p); } return nindy_fd;}/****************************************************************************** * ninDownload: * Ask NINDY to start up it's COFF downloader. Invoke 'sx' to perform * the XMODEM download from the host end. * * Return 1 on success, 0 on failure. ******************************************************************************/#define XMODEM "sx" /* Name of xmodem transfer utility */intninDownload( fn, quiet ) char *fn; /* Stripped copy of object file */ int quiet;{ char *p; /* Pointer to full pathname of sx utility */ int success; /* Return value */ int pid; /* Process ID of xmodem transfer utility */ WAITTYPE w; /* xmodem transfer completion status */ int wret; /* Value returned by wait */ char buf[200]; if ( old_nindy ){ return OninDownload( fn, quiet ); } /* Make sure the xmodem utility is findable. This must be done before * we start up the NINDY end of the download (NINDY will hang if we * don't complete the download). */ if ( ((p = exists("G960BIN",XMODEM,NULL,NULL,1)) == NULL) && ((p = exists("G960BASE","bin",XMODEM, NULL,1)) == NULL)#ifdef HOST && ((p = exists(DEFAULT_BASE,HOST,"bin",XMODEM,0)) == NULL)#endif ){ fprintf(stderr,"Can't find '%s' download utility\n",XMODEM); fprintf(stderr,"Check env variables G960BIN and G960BASE\n"); return 0; } if ( !quiet ){ printf( "Downloading %s\n", fn ); } /* Reset NINDY, wait until "reset-complete" ack, * and start up the NINDY end of the download. */ ninReset(); putpkt((unsigned char *) "D", 1 ); /* Invoke x-modem transfer, a separate process. DON'T * use system() to do this -- under system V Unix, the * redirection of stdin/stdout causes the nindy tty to * lose all the transmission parameters we've set up. */ success = 0;#if defined(USG) && !defined(HAVE_VFORK) pid = fork ();#else pid = vfork ();#endif if ( pid == -1 ){ perror( "Can't fork process:" ); } else if ( pid == 0 ){ /* CHILD */ dup2( nindy_fd, 0 ); /* Redirect stdin */ dup2( nindy_fd, 1 ); /* Redirect stout */ if ( quiet ){ execl( p, p, "-q", fn, (char*)0 ); } else { execl( p, p, fn, (char*)0 ); } /* Don't get here unless execl fails */ sprintf( buf, "Can't exec %s", p ); perror( buf ); } else { /* PARENT */ do { wret = wait(&w); } while ( wret != pid && wret != -1 ); if ( wret == -1 ){ perror( "Wait failed" ); } else if (WIFEXITED(w) && (WEXITSTATUS(w) == 0)){ success = 1; } } return success;}/****************************************************************************** * ninGdbExit: * Ask NINDY to leave GDB mode and print a NINDY prompt. ******************************************************************************/ninGdbExit(){ if ( old_nindy ){ OninGdbExit(); return; } putpkt((unsigned char *) "E", 1 );}/****************************************************************************** * 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). ******************************************************************************/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 */ if ( old_nindy ){ OninMemGet(ninaddr, hostaddr, len); return; } for ( ; len > 0; len -= BUFSIZE ){ cnt = len > BUFSIZE ? BUFSIZE : len; buf[0] = 'm'; put_int( &buf[1], ninaddr ); buf[5] = cnt & 0xff; buf[6] = (cnt>>8) & 0xff; send( buf, 7, hostaddr ); ninaddr += cnt; hostaddr += cnt; }}/****************************************************************************** * ninMemPut: * Write a string of bytes into NINDY's address space (960 memory). ******************************************************************************/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 */ if ( old_nindy ){ OninMemPut( ninaddr, hostaddr, len ); return; } for ( ; len > 0; len -= BUFSIZE ){ cnt = len > BUFSIZE ? BUFSIZE : len; buf[0] = 'M'; put_int( &buf[1], ninaddr ); bcopy( hostaddr, buf+5, cnt ); send( buf, cnt+5, NULL ); ninaddr += cnt; hostaddr += 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. * ******************************************************************************/longninRegGet( 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 get_int(inbuf);}/****************************************************************************** * 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); put_int( &buf[len], 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 */{ unsigned char buf[REGISTER_BYTES+10]; if ( old_nindy ){ OninRegsPut( regp ); return; } buf[0] = 'R'; bcopy( regp, buf+1, REGISTER_BYTES ); send( buf, 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(){ 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] = get_int(&buf[offset]); } /* 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 = ERROR; break; } /* Send request termination status to NINDY */ buf[0] = 'e'; put_int( &buf[1], 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) ******************************************************************************/charninStopWhy( 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]; bcopy (&buf[2], (char *)ipp, sizeof (*ipp)); bcopy (&buf[6], (char *)fpp, sizeof (*ipp)); bcopy (&buf[10], (char *)spp, sizeof (*ipp)); return buf[0];}/****************************************************************************** * ninStrGet: * Read a '\0'-terminated string of data out of the 960 memory space. * ******************************************************************************/staticninStrGet( 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] = '"'; put_int( &cmd[1], ninaddr ); send( cmd, 5, hostaddr );}/****************************************************************************** * 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" * * ******************************************************************************/intninVersion( p ) unsigned char *p; /* Where to place version string */{ if ( old_nindy ){ return OninVersion( p ); } send((unsigned char *) "v", 1, p ); return strlen(p);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -