📄 onindy.c
字号:
char *buf; /* Message to be sent to NINDY; replaced by * NINDY's response. */ int ack_required; /* TRUE means NINDY's response MUST be either "X00" (no * error) or an error code "Xnn". * FALSE 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(); }} /************************ * * * 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", B1200, "2400", B2400, "4800", B4800, "9600", B9600, "19200", B19200, "38400", B38400, 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. ******************************************************************************/staticstruct 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 it 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 saw_alarm;static voidalarm_handler(){ saw_alarm = 1;}static inttry_baudrate( fd, brp ) int fd; struct baudrate *brp;{ TTY_STRUCT tty; char c; int n; void (*old_alarm)(); /* Save alarm signal handler here on entry */ /* Set specified baud rate and flush all pending input */ ioctl( fd, TIOCGETP, &tty ); TTY_REMOTE( tty, brp->rate ); ioctl( fd, TIOCSETP, &tty ); tty_flush( fd ); /* Send bogus command */ write( fd, "\020#00", 4 ); /* Wait until reponse comes back or one second passes */ old_alarm = signal( SIGALRM,alarm_handler ); saw_alarm = 0; alarm(1); do { n = 1; TTY_NBREAD(fd,n,&c); } while ( n<=0 && !saw_alarm ); /* Turn off alarm */ alarm(0); signal( SIGALRM,old_alarm ); /* Did we get a '-' back ? */ if ( (n > 0) && (c == '-') ){ return 1; } return 0;}/****************************************************************************** * 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. ******************************************************************************/staticautobaud( fd, brp ) int fd; struct baudrate *brp;{ int i; TTY_STRUCT tty; say("NINDY at wrong baud rate? Trying to autobaud...\n"); i = 0; while ( 1 ){ say( "\r%s... ", baudtab[i].string ); if ( try_baudrate(fd,&baudtab[i]) ){ break; } if ( baudtab[++i].string == NULL ){ /* End of table -- wraparound */ i = 0; say("\nAutobaud failed. Trying again...\n"); } } /* Found NINDY's current baud rate; now change it. */ say("Changing NINDY baudrate to %s\n", brp->string); OninBaud( brp->string ); /* Change our baud rate back to rate to which we just set NINDY. */ ioctl( fd, TIOCGETP, &tty ); TTY_REMOTE( tty, brp->rate ); ioctl( fd, TIOCSETP, &tty );} /********************************** * * * 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. ******************************************************************************/OninBaud( baudrate ) char *baudrate; /* Desired baud rate, as a string of ASCII decimal * digits. */{ char buf[100]; /* Message buffer */ char *p; /* Pointer into buffer */ unsigned char csum; /* Calculated checksum */ tty_flush( nindy_fd ); /* 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( buf, "\020z%s#%02x", baudrate, csum ); write( nindy_fd, buf, strlen(buf) );}/****************************************************************************** * 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, FALSE );}/****************************************************************************** * 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, FALSE );}/****************************************************************************** * ninConnect: * Open the specified tty. Get communications working at the specified * Flush any pending I/O on the tty. * * Return the file descriptor, or -1 on failure. ******************************************************************************/intOninConnect( name, baudrate, brk, silent ) 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 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 }; quiet = silent; /* Make global to this file */ for ( i=0; prefix[i] != NULL; i++ ){ p = malloc(strlen(prefix[i]) + strlen(name) + 1 ); strcpy( p, prefix[i] ); strcat( p, name ); nindy_fd = open(p,O_RDWR); if ( nindy_fd >= 0 ){#ifdef TIOCEXCL /* Exclusive use mode (hp9000 does not support it) */ ioctl(nindy_fd,TIOCEXCL,NULL);#endif if ( brk ){ send_break( nindy_fd ); } brp = parse_baudrate( baudrate ); if ( brp == NULL ){ say("Illegal baudrate %s ignored; using 9600\n", baudrate); brp = parse_baudrate( "9600" ); } if ( !try_baudrate(nindy_fd,brp) ){ autobaud(nindy_fd,brp); } tty_flush( nindy_fd ); say( "Connected to %s\n", p ); free(p); break; } 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 */intOninDownload( 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 */ char buf[200]; /* 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. */ OninReset(); putpkt( "D" ); /* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -