Table of Contents

DMSREA Abstract

Statistics

Type ASSEMBLE
Source Lines : 645
Fixes Applied : 2
Most Recent Version : Tuesday, December 12, 1978
Last Fix ID : [R12074DS]

Synopsis

Function

       DMSREA IS AN INTERFACE MODULE FOR THE CMS CPEREP COMMAND.
       DMSREA READS A SPECIFIED LOGICAL RECORD FROM THE VM/370
       ERROR RECORDING CYLINDERS AND RETURNS IT TO THE CALLER.
       THE CALLER SPECIFIES WHICH LOGICAL RECORD HE WANTS BY
       PASSING A RECORD ADDRESS TO DMSREA.  THE RECORD ADDRESS
       FORMAT RESEMBLES THE STANDARD 5 BYTE CCHHR DISK ADDRESS
       FORMAT, BUT IS A LITTLE DIFFERENT.  THE FORMAT IS:
         CCB0R
       WHERE:
         CC - IS THE RELATIVE DASD CYLINDER ADDRESS (RELATIVE TO
              THE FIRST OF THE ERROR CYLINDERS, E.G., CC IS
              X'0000', X'0001', ...,X'0008').
         B  - IS THE NUMBER OF THE 4K BLOCK (OR PAGE) WITHIN THE
              SPECIFIED DASD CYLINDER.
         0  - A BYTE OF ZERO.
         R  - LOGICAL RECORD NUMBER OF A RECORD WITHIN THE
              SPECIFIED BLOCK.  THE BLOCK CONTAINS VARIABLE LENGTH
              RECORDS, EACH PRECEEDED BY THE STANDARD 4 BYTE RECORD
              DESCRIPTOR WORD WHICH CONTAINS THE RECORD LENGTH.
              SINCE RECORDS IN THE ERROR RECORDING CYLINDERS ARE
              NEVER LESS THAN 24 BYTES IN LENGTH, THERE CANNOT BE
              MORE THAN 255 RECORDS IN A BLOCK.  RECORDS WITHIN
              A BLOCK ARE NUMBERED 1 THRU M.
       THE CCB0R ADDRESS IS NOT ONLY RECEIVED FROM THE CALLER,
       BUT IS RETURNED TO HIM AFTERWARDS AS WELL, FOR REASONS
       THAT WILL SOON BE APPARENT.  SOMETIMES THE REQUESTED RECORD
       DOES NOT EXIST OR CANNOT BE READ (DUE TO AN I/O ERROR).
       IN THESE CASES, THE NEXT LOGICAL RECORD IS RETURNED TO THE
       CALLER INSTEAD.  AND IN THESE CASES THE CCB0R ADDRESS
       RETURNED TO THE CALLER IS A CORRECTED CCB0R ADDRESS THAT
       SHOWS WHAT RECORD WAS ACTUALLY GOTTEN.  SOME EXAMPLES
       WILL CLARIFY THIS.

       ASSUMPTIONS FOR EXAMPLES:
         * EACH CYLINDER CONTAINS 10 (=X'0A') OF THE 4K BLOCKS.
         * NO RECORDS WERE RECORDED IN THE 1ST (CC=X'0000') CYLINDER,
           I.E., ALL 10 BLOCKS THERE ARE FLAGGED AS EMPTY.
         * BLOCK 1 IN THE 2ND CYLINDER CONTAINS 7 RECORDS.
         * BLOCK 2 IN THE 2ND CYLINDER IS FLAGGED AS UNREADABLE OR
           EMPTY.
         * BLOCK 3 IN THE 2ND CYLINDER CONTAINS 5 RECORDS.
         * BLOCK 4 IN THE 2ND CYLINDER CONTAINS 3 RECORDS.
         * THE REMAINING BLOCKS OF THE 2ND CYLINDER ARE EMPTY.
       EXAMPLE 1:
         THE CALLER PASSES X'0001030005' AS THE CCB0R ADDRESS.
         THE REQUESTED RECORD 5 IN BLOCK 3 OF THE 2ND CYLINDER
         EXISTS, SO THE REQUESTED RECORD IS RETURNED.  AND THE
         ORIGINAL CCB0R VALUE IS RETURNED UNCHANGED.
       EXAMPLE 2:
         THE CALLER WANTS TO READ THE NEXT SEQUENTIAL RECORD AFTER
         THE ONE HE READ IN EXAMPLE 1.  SO HE ADDS 1 TO THE R
         VALUE OF THE CCB0R ADDRESS RETURNED IN EXAMPLE 1, GETTING
         X'0001030006', WHICH HE NOW PASSES TO DMSREA.  SINCE
         THERE IS NO RECORD 6 IN BLOCK 3, DMSREA RETURNS THE NEXT
         AVAILABLE RECORD WHICH IS RECORD 1 IN BLOCK 4.  AND THE
         RETURNED ADDRESS IS X'0001040001'.
       EXAMPLE 3:
         THE CALLER PASSES X'0001010008' AS THE CCB0R ADDRESS.
         THERE IS NO RECORD 8 IN BLOCK 1, SO DMSREA TRIES TO GET
         RECORD 1 FROM BLOCK 2, BUT BLOCK 2 IS FLAGGED AS
         UNREADABLE, SO IT ADVANCES TO BLOCK 3 AND RETURNS RECORD
         1 OF BLOCK 3.  THE RETURNED ADDRESS IS X'0001030001'.
       EXAMPLE 4:
         THE CALLER PASSES X'0000050005', ATTEMPTING TO READ
         NON-EXISTENT DATA FROM THE EMPTY 1ST CYLINDER.  DMSREA
         SCANS THRU BLOCKS 5 THRU 10 OF THE 1ST CYLINDER, FINDING
         NOTHING, AND THEN SWITCHES TO THE 2ND CYLINDER.  THERE
         IT FINDS AND RETURNS RECORD 1 OF BLOCK 1 AND RETURNS
         THE ADDRESS X'0001010001'.
       EXAMPLE 5:
         THE CALLER PASSES X'00000B0001', ATTEMPTING TO READ FROM
         THE 1ST CYLINDER, BUT BEYOND THE ALLOWED LIMIT OF
         10 (=X'0A') BLOCKS PER CYLINDER (AS ASSUMED FOR THIS
         EXAMPLE).  THIS IS NOT ALLOWED.  THE RESULTS ARE
         UNPREDICTABLE.  (NOTE: THE CALLER IS NOT EXPECTED TO
         KNOW HOW MANY BLOCKS ARE ALLOWED IN A CYLINDER ON A
         PARTICULAR DEVICE.  RATHER, IT IS EXPECTED THAT HE WILL
         ONLY USE ADDRESSES THAT HAVE BEEN RETURNED TO HIM FROM
         PRIOR CALLS TO DMSREA, WITH ONLY THE R FIELD CHANGED BY
         HIM.  AN EXCEPTION IS THAT HE IS PERMITTED TO MAKE UP
         AN ADDRESS HIMSELF TO GET STARTED AT THE FIRST BLOCK
         OF EITHER CYLINDER.)
       EXAMPLE 6:
         THE CALLER PASSES X'0001040004' REQUESTING A RECORD
         FOLLOWING THE FINAL RECORD OF BLOCK 4, 2ND CYLINDER.
         BLOCKS BEYOND BLOCK 4 ARE ALL EMPTY.  DMSREA LOOKS FOR,
         BUT FAILS TO FIND, A NEXT AVAILABLE RECORD IN THE
         REMAINING BLOCKS.  SO DSMREA RETURNS AN END-OF-FILE
         INDICATION RATHER THAN A NEXT AVAILABLE RECORD.
       EXAMPLE 7:
         FORGET THE ASSUMPTIONS OF THE EARLIER EXAMPLES.  ASSUME
         NOW THAT ALL CYLINDERS ARE EMPTY. THE CALLER PASSES
         X'0000010001' REQUESTING THE FIRST RECORD OF THE FIRST
         CYLINDER. DMSREA READS THRU ALL CYLS LOOKING FOR
         AN AVAILABLE RECORD AND FINALLY RETURNS AN END-OF-FILE
         INDICATION RATHER THAN A RECORD.

Operation

       1. SAVE REGISTERS AS NECESSARY.  SET R15 RETURN CODE TO 0.
       2. IF THIS IS NOT THE FIRST CALL TO DMSREA, GO TO 4.
       3. ISSUE DIAGNOSE X'2C' TO FIND THE START OF THE VM/370
          ERROR RECORDING CYLINDERS.  STORE RETURNED ADDRESS VALUE
          IN 'STARTCYL'.  'AVAILBLK' IS INITIALLY ZERO; NON-EXISTENT
          ZERO ADDRESS INSURES THAT IN CODE BELOW WE DO NOT GET
          FOOLED INTO THINKING 4K BUFFER CONTAINS A BLOCK.
          THROW 'FIRST TIME' SWITCH. STORE COUNT OF RECORD-
          ING CYLINDERS IN 'CYLCOUNT'.
       4. CHECK CC PORTION OF INPUTTED CCB0R FOR VALID RANGE.
          IF INVALID, GO TO 16.
       5. CONVERT CCB PORTION OF INPUTTED CCB0R ADDRESS TO A
          'VM/370 CONTROL PROGRAM INTERNAL FORMAT (CPIF)' ADDRESS.
       6. IF COMPUTED CPIF ADDRESS MATCHES VALUE IN 'AVAILBLK',
          THEN DESIRED BLOCK IS ALREADY IN BUFFER, SO GO TO 11.
       7. SET 'RECNO' TO ZERO INDICATING WE HAVE NOT YET COUNTED UP
          TO ANY PARTICULAR RECORD IN THE NEW BLOCK ABOUT TO BE
          READ IN.  SET 'AVAILBLK' TO ZERO (WE COULD ALMOST AS WELL
          SET IT TO THE NEW CPIF ADDRESS SINCE WE ARE ABOUT TO
          READ THAT BLOCK INTO THE BUFFER; BUT THE READ COULD FAIL
          AND ZERO BEST INDICATES UNDEFINED STATE OF THE BUFFER).
          ISSUE DIAGNOSE X'30' USING COMPUTED CPIF ADDRESS TO READ
          THE ADDRESSED BLOCK.  TEST CONDITION CODE SET BY DIAGNOSE:
             CC=0: BLOCK WAS READ SUCCESSFULLY; GO TO 10.
             CC=1: END OF CYLINDER, ADDRESSED BLOCK IS NON-EXISTENT;
                   GO TO 17.
             CC=3: SPECIFIED CYLINDER IS OUTSIDE THE ERROR RECORDING
                   AREA; GO TO 16.
             CC=2: I/O ERROR,BLOCK COULD NOT BE READ; FALL THRU TO 8.
       8. ISSUE MESSAGE DMSREA830E (I/O ERROR), SET CODE 60 FOR R15.
          (WE CANNOT GET THE ADDRESSED RECORD, SO WE WILL TRY FOR
          THE NEXT AVAILABLE RECORD INSTEAD.)
       9. PREPARE TO READ NEXT BLOCK AND USE FIRST RECORD IN IT:
          ADD ONE TO BLOCK NUMBER IN CPIF ADDRESS; SET R VALUE OF
          CCB0R TO RECORD 1; GO TO 7.

      10. STORE CPIF ADDRESS IN 'AVAILBLK'.
          IF THE BLOCK IS FLAGGED AS EMPTY, GO TO 9.
      11. (COMMENT: BLOCK SPECIFIED BY CPIF ADDRESS IS NOW IN THE
          BUFFER AND DOES CONTAIN SOME RECORDS.  'RECNO' AND
          'RECADDR' EITHER POINT TO SOME RECORD IN THE BUFFER OR
          'RECNO' IS ZERO.  R IN CCB0R SPECIFIES THE RECORD WE
          WANT TO FIND IN THE BUFFER.)
          IF 'RECNO' IS GREATER THAN R, SET 'RECNO' TO ZERO.
      12. IF 'RECNO' IS ZERO, SET IT TO ONE AND INITIALIZE
          'RECADDR' TO POINT TO FIRST RECORD IN BUFFER.
      13. (COMMENT: STEP THRU THE BUFFER INCREMENTING 'RECNO'
          AND 'RECADDR' UNTIL 'RECNO' MATCHES R OR UNTIL THERE
          ARE NO MORE RECORDS IN THE BUFFER.)
          IF 'RECNO' EQUALS R, GO TO 14.
          INCREMENT 'RECNO' BY ONE AND ADVANCE 'RECADDR' TO NEXT
          RECORD, IF ANY.
          IF 'RECADDR' IS BEYOND LAST RECORD IN BUFFER, GO TO 9.
          OTHERWISE, LOOP TO 13 FOR ANOTHER ITERATION.

      14. FROM THE CURRENT R AND CPIF ADDRESS, COMPUTE A CORRECTED
          CCB0R VALUE TO BE RETURNED TO THE CALLER.  PUT ADDRESS
          OF CORRECTED CCB0R DATA IN R1.  LOAD 'RECADDR' INTO R0.
      15. RESTORE REGISTERS (EXCEPT OUTPUT PARAMETER REGISTERS) AND
          RETURN TO THE CALLER.

      16. SET ERROR CODE IN R15 FOR INVALID CYLINDER.  GO TO 15.

      17. (COMMENT: END OF CYLINDER INDICATION WAS RECEIVED.)
          SET R0 TO ZERO (INDICATES EOF TO CALLER IN CASE THIS
          CYLINDER IS THE LAST CYLINDER).
          IF CC PORTION OF CPIF ADDRESS INDICATES WE WERE ALREADY
          ON THE FINAL CYLINDER, GO TO 15.
          OTHERWISE ADVANCE TO NEXT CYLINDER: ADD 1 TO CC OF CPIF
          ADDRESS; SET B OF CPIF ADDRESS TO BLOCK 1; SET R OF CCB0R
          ADDRESS TO RECORD 1;
          GO TO 7 (TO READ FIRST AVAILABLE RECORD IN NEXT CYLINDER).

Calls to Other Routines

       DIAGNOSE CALLS TO CP AS BELOW:
            DIAGNOSE CODE X'2C' = FIND RECORDING AREA ON SYSTEM DISK.
            DIAGNOSE CODE X'30' = READ PAGE SIZE RECORD FROM ERROR
            RECORDING CYLINDERS.
       DMSERR - CALLED VIA MACRO SVC TO WRITE ERROR MESSAGE TO
                THE CONSOLE.