/* BEGIN DOCUMENTATION Name: LOOP.C Created: 04/26/84 DTS Last Update: 04/30/84 Title: Loopback Test for RIA system Index: Loopback Test, Diagnostics Abstract: Output to port that has loopback connector attached, check for compare errors on input. Usage: LOOP term Parameters: term - Terminal port to which test is run. Special Input characters from terminal: Control-C Terminate test program. Control-W or Control-R Refresh entire screen. Environment: RSX11M V4.0, RSX11M+ V2.1, DECUS C See Also: IICHECK for RIA instrument interface micro computers. Description: Outputs a continuous stream of characters to named terminal port. Inputs from same port and checks for match of characters. Any errors are reported to console. Test runs until ^C pressed. Every 32 characters a message is printed with the pass number. Each pass contains 128 different characters which are output to the port under test. If no characters are returned for 20 seconds the routine will timeout and terminate the current pass. The port under test and TI: are both set to typeahead & full duplex. LOOP assumes a VT100 or VT52 is the terminal starting the test. In addition to the pass count and count of compare errors a message is output containing the I/O result code returned in the I/O status block (iosb) whenever it is not IS_SUC (1). Example(s): Input Command: LOOP TT5: (to run test to port TT5) Output Display: (Clear screen) Serial loopback test for port TT5: Pass Number 2 Passes with errors = 1 Input timeouts = 1 Characters output = 32 Characters input in error = 10 Last bad compare output = 40, input = 0, pass = 1. The test runs continously, updating the counters on the screen until a control-C is pressed. Note that all numbers are displayed in decimal except the input & output character values which are displayed in octal. Uses: Used for RIA testing with instrument interface running software loopback. In this mode the port under test should be set to 'SLAVE', then the instrument interface micro should be started from location IICHECK+4, and then the loopback test should be started from the PDP-11. Internal: Uses AST to asynchonously input from terminal port (TI:) Update History: END DOCUMENTATION */ #include #include #include /* #define debug 0 */ #define BUFSIZ 800 /* Output buffer size */ #define BSIZ 128 /* test buffer size */ #define BLOCKSIZ 32 /* I/O block size */ #define TIFLAG 4 /* Event flags for input */ #define INFLAG 5 #define WTMASK 030 /* Or of flag 4 & flag 5 */ #define TILUN 4 /* Lun for terminal TI */ #define TTLUN 5 /* Lun for external port */ #define IS_TMO 002 #define IO_ATT 01400 #define IO_RAL 01010 #define IO_RST 01001 #define IO_WVB 011000 #define IO_WAL 0410 #define IO_KIL 012 #define IO_DET 02000 #define TF_ESQ 020 #define TF_NOT 002 #define TF_RNE 020 #define TF_TMO 0200 #define SF_SMC 02440 /* Set multiple characteristics */ #define TC_WID 01 /* Terminal Width */ #define TC_RAT 07 /* Typeahead mode - RSX11M only */ #define TC_ACR 024 /* Wrap */ #define TC_FDX 064 /* Full duplex */ extern int qio(); /* DECUS C library - RSX functions */ extern int qiow(); extern wtse(); extern wtlo0(); extern int $dsw; extern rdast(); /* Forward reference */ int iosbin[2]; /* I/O status blocks */ int iosbout[2]; int iosbti[2]; int devpar[6]; /* Qio parms */ int indpar[6]; int otdpar[6]; static char tichar; /* Character input from console */ static char inch = EOS; /* Last character transmitted in error */ static char outch = EOS; /* Last character read in error */ static long int chcnt = 0; /* Status counters for display */ static int passcnt = 1; static int passerr = 0; /* Error counters for display */ static long int cherr = 0; /* Characters received in error */ static int timeout = 0; /* Characters received in error */ char obuf[BSIZ]; /* Output buffer for test */ char ibuf[BSIZ]; /* Input buffer for test */ static char buff[BUFSIZ]; static char term[]= "TI0: "; /* Console Device Name */ char port[5]; boolean abort,comperr,timoterr; /* Globals returned to main */ main(argc,argv) char *argv[]; { register int i,c; char **oldbuf; iff argc != 2 or ((c = strlen(argv[1])) > 5) or (c < 2) then error("Format is: LOOP TTn:"); cpystr(port,argv[1]); /* Initialize Test */ attach(term,TILUN); /* Attach Terminals */ attach(port,TTLUN); iosbin[0] = iosbout[0] = IS_SUC; /* Default to good */ for(i = 0; i < BSIZ; i++) /* Initialize output buffer */ obuf[i] = (char) i; /* Set buffered output & clear screen */ iff scset(buff,sizeof(buff),&oldbuf) == 0 then error("Scset error"); dispscrn(); /* Display static screen */ readti(); /* Check for control C */ /***********************************************\ * MAIN PROCEDURE: * * DO forever: * * Output Pass # * * output error count * * INPUT 256 CHARACTERS (async w/ timeout) * * OUTPUT 256 char Test pattern * * WAIT for input done * * If ^C from TI: abort * * else check for errors * * If timeout error Kill I/O to test port * * END DO * ************************************************/ repeat /* Cycle forever */ { comperr = timoterr = false; for(c = 0; (c < BSIZ) and (not abort); c += BLOCKSIZ) { dispstat(); /* Display status */ indpar[0] = &ibuf[c]; /* Start of i/o */ indpar[1] = BLOCKSIZ; /* I/O count */ indpar[2] = 2; /* Timeout, 10 sec intervals */ /* Input from test port */ iff qio(IO_RAL | TF_TMO | TF_RNE,TTLUN,INFLAG,iosbin,0,indpar) < 0 then error("\nRead qio error, dsw = %d",$dsw); otdpar[0] = &obuf[c]; /* Start of i/o */ otdpar[1] = BLOCKSIZ; /* I/O count */ otdpar[2] = 0; /* No vfc added to output */ /* Output test pattern */ iff qio(IO_WAL,TTLUN,0,iosbout,0,otdpar) < 0 then error("\nRead qio error, dsw = %d",$dsw); wtlo0(WTMASK); /* Wait for Input Done before Retesting */ iff !(abort) then { compbuf(&ibuf[c],&obuf[c]); /* Test for errors */ chcnt += BLOCKSIZ; iff timoterr then /* Abort pass on timeout */ { timeout++; iff qio(IO_KIL,TTLUN,INFLAG,iosbin,0,0) < 0 then /* Stop I/O */ error("\nTimeout I/O Kill error, dsw = %d",$dsw); wtlo0(WTMASK); /* Wait for QIO Done or abort */ break; /* Break from for loop */ } } } iff comperr then passerr++; passcnt++; } untill(abort)); /* scout(0,0,NULL); * Flush buffers * scput(oldbuf); */ detach(TILUN); detach(TTLUN); } /* end main */ /*** ATTACH: Attach Named Terminal, Set full duplex & typeahead ***/ proc attach(devnam,lun) char *devnam; int lun; { union { int dev; char name[2]; } dnam; static int fnc; /* parm definitions for qio */ static int unit,eflag; static int ttchar[6]; register int i,c; /* assign device to given lun */ for (i = 0; i < 2; i++) dnam.name[i] = ifx islower(c = *devnam++) thenx c - ('a' - 'A') elsex c; unit = otoi(devnam); #ifdef debug printf("Dev = '%c%c', Unit = %d\n",dnam.name[0],dnam.name[1],unit); #endif alun(lun,dnam.dev,unit); /* Attach terminal to capture all characters & allow typeahead */ fnc = IO_ATT; eflag = TIFLAG; iosbti[0] = 0; devpar[0] = 0; devpar[1] = 0; devpar[2] = 0; iff qiow(fnc,lun,eflag,iosbti,0,devpar) < 0 then error("\nAttach error dsw = %d\n",$dsw); /* Set terminal characteristics for fullduplex & typeahead */ fnc = SF_SMC; ttchar[0] = TC_FDX + 256; /* Set full duplex */ ttchar[1] = TC_ACR + 0; /* Clear wrap */ ttchar[2] = TC_RAT + 256; /* Set typeahead */ ttchar[3] = TC_WID + (256 * BSIZ); /* Set width if not TI: */ devpar[0] = &ttchar; devpar[1] = ifx dnam.name[1] == 'I' thenx 6 elsex 8; /* Bytes in ttchar table */ iff qiow(fnc,lun,eflag,iosbti,0,devpar) < 0 then error("\nATTACH - SMC error dsw = %d\n",$dsw); } /* end attach */ /*** Detach terminal & kill outstanding I/O ***/ proc detach(lun) int lun; { iff qio(IO_KIL,lun,0,iosbti,0,0) < 0 then error("\nI/O Kill error, lun %d",lun); iff qio(IO_DET,lun,lun+2,iosbin,0,0) < 0 /* was qiow */ then error("\nDetach error, lun %d",lun); } /* end detach */ /*** OTOI: Convert Octal Ascii number to Integer ***/ int proc otoi(octnum) char *octnum; { register int i, c; for (i = 0; ((c = *octnum++) >= '0') and ((c -= '0') < 8); i += c) i <<=3; return(i); } /* end otoi */ /*** DISPSCRN: Display initial screen ***/ proc dispscrn() { scerpg(1,1); scout(2,20,"Serial loopback test for port"); scout(2,50,port); scout(6,20,"Pass Number"); scout(8,20,"Passes with errors ="); /* scout(8,50,"Input timeouts ="); */ scout(10,20,"Characters output ="); scout(12,20,"Characters input in error ="); } /* end dispscrn */ /*** DISPSTAT: Display counters to screen ***/ proc dispstat() { char temp[80]; sprintf(temp,"%u ",passcnt); scout(6,32,temp); /* Pass count */ sprintf(temp,"%u Input timeouts = %u ",passerr,timeout); scout(8,41,temp); /* Passes in error */ sprintf(temp,"%lu ",chcnt); scout(10,41,temp); /* Characters output */ sprintf(temp,"%lu ",cherr); scout(12,49,temp); /* Characters input in error */ iff (iosbin[0] & 0377) != IS_SUC then { sprintf(temp,"Input error, iosb = %o, %o ",iosbin[0],iosbin[1]); scout(16,10,temp); } else scerln(16,10); iff (iosbout[0] & 0377) != IS_SUC then { sprintf(temp,"Output error, iosb = %o, %o ",iosbout[0],iosbout[1]); scout(18,10,temp); } else scerln(18,10); iff inch != outch then { sprintf(temp,"Last bad compare output = %o, input = %o, pass = %u. ",(int) outch, (int) inch,passcnt); scout(20,10,temp); } scout(23,1,NULL); /* Flush buffer */ } /* end dispstat */ /*** COMPBUF: Compare input buffer to output buffer, increment error counters ***/ proc compbuf(ich,och) register charpointer ich,och; { register int i,count; inch = outch = EOS; iff (iosbin[0] & 0377) == IS_TMO then { timoterr = true; /* Set timeout flag */ count = iosbin[1]; } else count = BLOCKSIZ; for(i = 0; i < count; i++) iff *ich++ != *och++ then /* Compare characters in buffer */ { cherr++; /* Increment character error count */ inch = *(ich - 1); outch = *(och - 1); } iff (inch != outch) or (count < BLOCKSIZ) then comperr = true; /* Mark passes in error */ } /* end compbuf */ /*** READTI: Use Qio to Read one character from TI: ***/ /*** Set for RDAST routine to check ^C ***/ /*** Clears TIFLAG until character ready ***/ proc readti() { /*** Do qio IO.RST for 1 character. ***/ devpar[0] = &tichar; /* Set start of I/O */ devpar[1] = 1; /* Number of characters */ devpar[2] = 0; /* No Timeout */ iff qio(IO_RST | TF_RNE,TILUN,TIFLAG,iosbti,rdast,devpar) < 0 then error("TI: Read error, dsw = %d",$dsw); } /* end readti */ /*** rdast: entered when read is done, Sets abort if ^C ***/ proc rdast() { register pointer iosba; register int stat; astset(); /* Save registers */ iosba = gtdp(0); /* Get IOSB addr from stack */ iff (stat = *iosba & 0377) == IS_SUC then { iff iosbti[1] == 0 then tichar = (char) (iosbti[0] >> 8); /* High byte is terminator */ iff tichar == '\03' then /* ^c */ abort = true; else iff (tichar == '\027') or (tichar == '\018') then /* ^w or ^r */ { dispscrn(); /* Refresh display */ dispstat(); } } else iff stat != IS_TMO then { abort = true; /* Note: TIFLAG is still set */ } iff not abort then readti(); /* Fire off next qio, clear flag */ astx(1); /* remove iosb from stack on exit */ } /* end rdast */