!* 
!*    Amended 30th June 1982 to get MAXPAGE from properties table.
!*
!
! REVISED VERSION 19MAR79 TO KEEP DISC QUEUES FULL ALL THE TIME
! FOR TESTING QUEUEING EFFICENCY AS WELL AS HARDWARE
!
CONSTSTRING  (23) VERSION = "Vsn 30th March 1983
"
RECORDFORMAT  PF(INTEGER  DEST, SRCE, P1, P2, P3, P4, P5, P6)
RECORDFORMAT  COMF(INTEGER  OCPTYPE,SLIPL,SBLKS,SEPGS,NDISCS,DLVNADDR, C 
         (INTEGER  GPCTABSIZE,GPCA OR  INTEGER  DCUTABSIZE,DCUA), C 
         INTEGER  SFCTABSIZE,SFCA,SFCK,DIRSITE,  C 
         DCODEDA,SUPLVN,TOJDAY,DATE0,DATE1,DATE2,  C 
         TIME0,TIME1,TIME2,EPAGESIZE,USERS,CATTAD,SERVAAD,  C 
         BYTEINTEGER  NSACS,RESV1,SACPORT1,SACPORT0, C 
         NOCPS,RESV2,OCPPORT1,OCPPORT0,INTEGER  ITINT,CONTYPEA, C 
         (INTEGER  GPCCONFA OR  INTEGER  DCUCONFA), C 
         INTEGER  FPCCONFA,SFCCONFA,BLKADDR,RATION, C 
         (INTEGER  SMACS OR  INTEGER  SCUS), C 
         INTEGER  TRANS,LONGINTEGER  KMON,  C 
         INTEGER  DITADDR,SMACPOS,SUPVSN,PSTVA,SECSFRMN,SECSTOCD, C 
         SYNC1DEST,SYNC2DEST,ASYNCDEST,MAXPROCS,INSPERSEC,ELAPHEAD, C 
         COMMSRECA,STOREAAD,PROCAAD,SFCCTAD,DRUMTAD,TSLICE,FEPS,  C 
         MAXCBT,PERFORMAD,SP1,SP2,SP3,SP4,SP5,SP6, C 
         LSTL,LSTB,PSTL,PSTB,HKEYS,HOOT,SIM,CLKX,CLKY,CLKZ,  C 
         HBIT,SLAVEOFF,INHSSR,SDR1,SDR2,SDR3,  C 
         SDR4,SESR,HOFFBIT,BLOCKZBIT,BLKSHIFT,BLKSIZE,END)
RECORDFORMAT  DDTFORM(INTEGER  SER,PTS,PROPADDR); ! minimal DDT format
RECORDFORMAT  PROPFORM(INTEGER  TRACKS,CYLS,PPERTRK,BLKSIZE, C 
      TOTPAGES,RQBLKSIZE,LBLKSIZE,ALISTSIZE,KEYLEN,SECTINDX)
CONSTRECORD (COMF)NAME  COM=X'80C00000'
!*
CONSTINTEGER  MAXLVN = 99
CONSTINTEGER  READPAGEDEST = X'00210001'
CONSTINTEGER  GETPAGEDEST = X'50000'
CONSTINTEGER  RETURNPAGEDEST = X'60000'
CONSTINTEGER  MAXQUEUE = 128;            !MAX VALUE OF QUEUE
CONSTINTEGER  MAXTOTAL QUEUE = 256;      !MAX VALUE OF DISKS*QUEUE
CONSTINTEGER  MAXDISKS = 8
EXTERNALROUTINESPEC  DOUT(RECORD (PF)NAME  P)
EXTERNALROUTINESPEC  DPON(RECORD (PF)NAME  P)
EXTERNALROUTINESPEC  DPOFF(RECORD (PF)NAME  P)
EXTERNALROUTINESPEC  PROMPT(STRING  (15) S)

   EXTERNALROUTINE  RANDREAD(STRING  (255) S)
   INTEGER  LOOP, DISKS, QUEUE, L, D, Q, ITERATIONS, I, CDEX
   INTEGER  ABUFFER, TOTALFAULTS, FDEV, TOTPONNED, TOTPOFFED
   INTEGERARRAY  LVN,MAXPAGES,FAULT(1 : MAXDISKS)
   INTEGERNAME  MAXPAGE
   RECORD (DDTFORM)NAME  DDT
   RECORD (PROPFORM)NAME  PROP
   RECORD (PF)  P

      ROUTINE  FAIL(STRING  (255) S)
         PRINTSTRING(S)
         NEWLINE
         STOP 
      END ;                             !OF FAIL

      INTEGERFN  NEXTRAND
      INTEGER  I
      OWNINTEGER  RCONST = 1234567
         *LSS_RCONST
         *IMYD_65539
         *STUH_B 
         *AND_X'7FFFFFFF'
         *ST_I
         *ST_RCONST
         RESULT  = I-(I//MAXPAGE)*MAXPAGE
      END ;                             !OF NEXTRAND

      ROUTINE  PONREAD(INTEGER  DEV)
      RECORD (PF)  P
         P = 0
         P_DEST = READPAGEDEST
         P_P1 = (M'RRR'<<8)!DEV
         P_P2 = DEV<<24!NEXTRAND
         P_P3 = ABUFFER
         DPON(P)
      TOT PONNED=TOT PONNED+1
      END ;                             !OF PONREAD
      PRINTSTRING(VERSION)
!*
!CLEAR OUT FAULT RECORDS
!*
      TOTALFAULTS = 0
      CYCLE  D = 1,1,MAXDISKS
         FAULT(D) = 0
      REPEAT 
!FIRST READ IN NO OF DISKS AND THEIR LVNS
      PROMPT("No. of disks:")
      READ(DISKS)
      UNLESS  0 < DISKS <= MAXDISKS C 
         THEN  FAIL("Invalid no. of disks")
      PROMPT("Disk lvns:")
      CYCLE  D = 1,1,DISKS;             !NOW READ IN THEIR LVNS
         READ(LVN(D))
         UNLESS  0 <= LVN(D) <= MAXLVN C 
            THEN  FAIL("Invalid disk number")
         IF  D > 1 START ;              !CHECK FOR DUPLICATE DISKS
            CYCLE  I = 1,1,D-1
               IF  LVN(D) = LVN(I) THEN  FAIL( C 
                  "Duplicate disk specified")
            REPEAT 
         FINISH 
         I=BYTEINTEGER(COM_DLVNADDR+LVN(D))
         IF  I>=COM_NDISCS THEN  FAIL("Disc not avaliable")
         DDT==RECORD(INTEGER(COM_DITADDR+4*I))
         PROP==RECORD(DDT_PROPADDR)
         MAXPAGES(D)=PROP_TOTPAGES
      REPEAT 
!NOW READ IN Q SIZE
      PROMPT("Qs per disk:")
      READ(QUEUE)
      UNLESS  0 < QUEUE <= MAXQUEUE C 
         THEN  FAIL("Invalid queue size")
      IF  QUEUE*DISKS > MAXTOTAL QUEUE C 
         THEN  FAIL("Total queue too large")
!NOW READ IN NO OF READS
AGAIN:
      PROMPT("reads/disk:")
      READ(ITERATIONS)
      IF  ITERATIONS < 1 THEN  FAIL("Invalid no. of reads")
      LOOP = ITERATIONS*DISKS
      TOT PONNED = 0
      TOT POFFED = 0
!NOW GET A PAGE
      P = 0;                            !CLEAR RECORD
      P_DEST = GETPAGEDEST
      DOUT(P)
      CDEX = P_P2;                      !USED FOR RETURN PAGE
      ABUFFER = P_P4
!*
!NOW DO THE READS
!*
         CYCLE  Q = 1,1,QUEUE
            CYCLE  D = 1,1,DISKS
               MAXPAGE==MAXPAGES(D)
               PONREAD(LVN(D))
            REPEAT 
         REPEAT 
         CYCLE  
            DPOFF(P)
            FDEV = P_P1&X'FF';       !DEVICE NO IN BOTTOM BYTE OF P1
            FOR  D=1,1,DISKS CYCLE 
               EXIT  IF  LVN(D)=FDEV
            REPEAT 
            IF  P_P2 # 0 START ;        !A FAULT HAS OCCURRED
               TOTAL FAULTS = TOTAL FAULTS+1
               FAULT(D) = FAULT(D)+1
            FINISH 
            TOT POFFED = TOT POFFED +1
            EXIT  IF  TOT POFFED = LOOP
            MAXPAGE==MAXPAGES(D)
            PONREAD(FDEV) IF  TOT PONNED < LOOP
         REPEAT 
!*
!NOW PRINT OUT FAULT INFO IF ANY
!*
      IF  TOTALFAULTS > 0 START 
         PRINTSTRING("Total fault record")
         NEWLINE
         PRINTSTRING("Lvn   faults")
         NEWLINE
         CYCLE  D = 1,1,DISKS
            IF  FAULT(D) > 0 START 
               WRITE(LVN(D),1)
               WRITE(FAULT(D),6)
               NEWLINE
            FINISH 
         REPEAT 
      FINISH  ELSE  PRINTSTRING("No faults
")
      PROMPT("More Y/N:")
      SKIPSYMBOL WHILE  NEXTSYMBOL = NL OR  NEXTSYMBOL = ' '
      READSYMBOL(I)
      IF  I = 'Y' START 
         SKIPSYMBOL WHILE  NEXTSYMBOL # NL ; !SKIP REST OF LINE IN CASE REPLY WAS 'YES'
         -> AGAIN
      FINISH 
!*
!NOW RETURN PAGE
      P = 0
      P_DEST = RETURNPAGEDEST
      P_P2 = CDEX
      DPON(P)
      PRINTSTRING("Test ends
")
   END ;                                !OF RANDREAD
ENDOFFILE