{"id":242,"date":"2011-12-09T11:08:52","date_gmt":"2011-12-09T17:08:52","guid":{"rendered":"http:\/\/tommysprinkle.com\/txxos\/?p=242"},"modified":"2021-04-17T18:26:06","modified_gmt":"2021-04-17T23:26:06","slug":"reading-a-pds-member","status":"publish","type":"post","link":"https:\/\/tommysprinkle.com\/txxos\/?p=242","title":{"rendered":"Reading A PDS Member"},"content":{"rendered":"<p>To read the data for a PDS member we fist have to locate the directory entry that points to the data. \u00a0We establish two loops to process through the directory. \u00a0The outer loop reads the directory blocks and the inner loop steps through the directory entries contained in the block.<\/p>\n<pre>DIRBLOOP DS    0H\r\n         SLR   R1,R1\r\n         IC    R1,R               GET RECORD NUMBER\r\n         LA    R1,1(,R1)          ADD\r\n         STC   R1,R                  ONE\r\n         LA    R1,IORB\r\n         BAL   R14,XIO\r\n*\r\n         LTR   R15,R15\r\n         BNZ   DIREOF\r\n*\r\n*\r\n         LA    R2,INBUF           POINTER TO PDS INDEX RECORD\r\n         SLR   R3,R3              GET LENGTH\r\n         ICM   R3,B'0011',0(R2)             USED\r\n         LA    R2,2(,R2)          POINT TO FIRST ENTRY\r\n         S     R3,=F'2'           ADJUST LENGTH<\/pre>\n<p>This code established the processing for the outer loop (Directory Block Loop). \u00a0It read through a directory one block at a time. \u00a0Register 3 is set to contain the\u00a0remaining\u00a0length of data in the block. \u00a0Register two is set to point to the next directory entry to be processed.<\/p>\n<p>Our CCW chain for reading the directory blocks is a SEEK, SEARCH ID EQUAL, TIC, READ DATA (length=256). \u00a0Because I allocated the data set and specified the number of directory blocks to be less than the number that will fit \u00a0on a single track, I know there is no need to increment the track. \u00a0In a more general approach we would have to deal with this issue.<\/p>\n<pre>DIRLOOP  DS    0H\r\n         C     R3,=F'0'           MORE DATA\r\n         BNH   DIRBLOOP                    AVAILABLE<\/pre>\n<pre>*<\/pre>\n<pre>         CLC   =XL8'FFFFFFFFFFFFFFFF',0(R2)  END OF DIRECOTRY?<\/pre>\n<pre>         BE    DIREOF\r\n*\r\n         CLC   =CL8'TXXNUC28',0(R2) IS THIS OUR ENTRY\r\n         BE    DIRFOUND\r\n*\r\n         SLR   R1,R1\r\n         ICM   R1,B'0001',11(R2)  GET C FIELD\r\n         N     R1,=A(X'1F')       GET USER DATA LENGTH\r\n         SLL   R1,1               MULTIPLY BY 2\r\n         LA    R1,12(,R1)         ADD IN FIXED LENGTH\r\n         AR    R2,R1              POINT TO NEXT ENTRY\r\n         SR    R3,R1              ADJUST LENGTH\r\n         B     DIRLOOP            PROCESS NEXT DIR ENTRY<\/pre>\n<p>This is the processing for the inner loop that steps through the directory entries contained in a single directory block. \u00a0First we check to see if there is another directory entry to process. \u00a0If not we go back to the outer loop and read another block.<\/p>\n<p>If we have and entry to process we check to see if the member name matches the name we are searching for. \u00a0If it matches we have found the entry we are looking for.<\/p>\n<p>If it doesn&#8217;t match we calculate the length of the user data. \u00a0We take the contents of the C field and mask off the top three bits. \u00a0This leaves the number of halfwords that make up the user data. \u00a0We 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. \u00a0We add 12 (the length of the member name and the TTRC) to the user data length to get the total length of the entry. \u00a0We use this value to point to the next directory entry and to adjust the remaining length of data to process in the block.<\/p>\n<p>Now that we have located the directory entry we have the relative offset (TTR) into the data set where the member data starts. \u00a0We can use this and the extent information from the DSCB to point to the first block of data.<\/p>\n<p>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. \u00a0A more general solution would require handling up to sixteen extents.<\/p>\n<pre>         SLR   R2,R2\r\n         SLR   R1,R1\r\n         SLR   R0,R0\r\n         ICM   R2,B'0011',TTRC   Relative Track Offset\r\n         ICM   R1,B'0011',BEGHH  Extent Begin HH\r\n         AR    R1,R2\r\n         ICM   R2,B'0011',BEGCC  Extent Begin CC\r\n         L     R15,TRKCYL        Tracks per Cylinder\r\n         DR    R0,R15            Calculate CC\/HH\r\n         AR    R2,R1             Add in Cylinder Offset\r\n         STCM  R2,B'0011',CC     Save CC\r\n         STCM  R0,B'0011',HH     Save HH\r\n         MVC   R(1),TTRC+2       Move In Record Offset<\/pre>\n<p>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. \u00a0We then divide by the number of tracks per cylinder. \u00a0This give us the cylinder offset which we add to the beginning cylinder of the extent. \u00a0The reminder is the track value. \u00a0The record value simply copied from the TTR offset to complete the CCHHR value for the first block of data.<\/p>\n<p><a title=\"DISK3 Assembly Listing \u2013 Part 1\" href=\"http:\/\/tommysprinkle.com\/txxos\/?p=247\">[Next &#8211; DISK3 Assembly Listing &#8211; Part 1]<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>To read the data for a PDS member we fist have to locate the directory entry that points to the data. \u00a0We establish two loops to process through the directory. \u00a0The outer loop reads the directory blocks and the inner &hellip; <a href=\"https:\/\/tommysprinkle.com\/txxos\/?p=242\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"template-page-builder-no-sidebar.php","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-242","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1CPQT-3U","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/242","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=242"}],"version-history":[{"count":6,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/242\/revisions"}],"predecessor-version":[{"id":499,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=\/wp\/v2\/posts\/242\/revisions\/499"}],"wp:attachment":[{"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=242"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=242"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommysprinkle.com\/txxos\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=242"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}