Type ASSEMBLE
Source Lines : 645
Fixes Applied : 2
Most Recent Version : Tuesday, December 12, 1978
Last Fix ID : [R12074DS]
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.