To read the data for a PDS member we fist have to locate the directory entry that points to the data.  We establish two loops to process through the directory.  The outer loop reads the directory blocks and the inner loop steps through the directory entries contained in the block.

DIRBLOOP DS    0H
         SLR   R1,R1
         IC    R1,R               GET RECORD NUMBER
         LA    R1,1(,R1)          ADD
         STC   R1,R                  ONE
         LA    R1,IORB
         BAL   R14,XIO
*
         LTR   R15,R15
         BNZ   DIREOF
*
*
         LA    R2,INBUF           POINTER TO PDS INDEX RECORD
         SLR   R3,R3              GET LENGTH
         ICM   R3,B'0011',0(R2)             USED
         LA    R2,2(,R2)          POINT TO FIRST ENTRY
         S     R3,=F'2'           ADJUST LENGTH

This code established the processing for the outer loop (Directory Block Loop).  It read through a directory one block at a time.  Register 3 is set to contain the remaining length of data in the block.  Register two is set to point to the next directory entry to be processed.

Our CCW chain for reading the directory blocks is a SEEK, SEARCH ID EQUAL, TIC, READ DATA (length=256).  Because I allocated the data set and specified the number of directory blocks to be less than the number that will fit  on a single track, I know there is no need to increment the track.  In a more general approach we would have to deal with this issue.

DIRLOOP  DS    0H
         C     R3,=F'0'           MORE DATA
         BNH   DIRBLOOP                    AVAILABLE
*
         CLC   =XL8'FFFFFFFFFFFFFFFF',0(R2)  END OF DIRECOTRY?
         BE    DIREOF
*
         CLC   =CL8'TXXNUC28',0(R2) IS THIS OUR ENTRY
         BE    DIRFOUND
*
         SLR   R1,R1
         ICM   R1,B'0001',11(R2)  GET C FIELD
         N     R1,=A(X'1F')       GET USER DATA LENGTH
         SLL   R1,1               MULTIPLY BY 2
         LA    R1,12(,R1)         ADD IN FIXED LENGTH
         AR    R2,R1              POINT TO NEXT ENTRY
         SR    R3,R1              ADJUST LENGTH
         B     DIRLOOP            PROCESS NEXT DIR ENTRY

This is the processing for the inner loop that steps through the directory entries contained in a single directory block.  First we check to see if there is another directory entry to process.  If not we go back to the outer loop and read another block.

If we have and entry to process we check to see if the member name matches the name we are searching for.  If it matches we have found the entry we are looking for.

If it doesn’t match we calculate the length of the user data.  We take the contents of the C field and mask off the top three bits.  This leaves the number of halfwords that make up the user data.  We can shift this value one bit to the left to multiply it by two which results in the number of bytes in the user data.  We add 12 (the length of the member name and the TTRC) to the user data length to get the total length of the entry.  We use this value to point to the next directory entry and to adjust the remaining length of data to process in the block.

Now that we have located the directory entry we have the relative offset (TTR) into the data set where the member data starts.  We can use this and the extent information from the DSCB to point to the first block of data.

For now we will require the data set to only consist of a single extent which will simplify the code to calculate the actual CCHHR.  A more general solution would require handling up to sixteen extents.

         SLR   R2,R2
         SLR   R1,R1
         SLR   R0,R0
         ICM   R2,B'0011',TTRC   Relative Track Offset
         ICM   R1,B'0011',BEGHH  Extent Begin HH
         AR    R1,R2
         ICM   R2,B'0011',BEGCC  Extent Begin CC
         L     R15,TRKCYL        Tracks per Cylinder
         DR    R0,R15            Calculate CC/HH
         AR    R2,R1             Add in Cylinder Offset
         STCM  R2,B'0011',CC     Save CC
         STCM  R0,B'0011',HH     Save HH
         MVC   R(1),TTRC+2       Move In Record Offset

To get the CCHHR for the first record of the member data we add the track offset (TT) value to the beginning head (HH) of the extent.  We then divide by the number of tracks per cylinder.  This give us the cylinder offset which we add to the beginning cylinder of the extent.  The reminder is the track value.  The record value simply copied from the TTR offset to complete the CCHHR value for the first block of data.

[Next – DISK3 Assembly Listing – Part 1]