The DISK1 program will read and dump records from our DASD volume.  Most of the work will be done in a subroutine called DUMPREC.  It will read a block given a CCHHR address and dump the contents to the printer.

 DUMPREC  DS    0H                                                  
          ST    R14,DUMPRCXT       SAVE RETURN ADDRESS              
          LA    R1,CCWSEEK         POINT TO CCW  CHAIN              
          ST    R1,72              SAVE INTO CAW                    
          LA    R2,X'345'          DISK DEVICE ADDRESS              
          SIO   0(R2)              START I/O                        
          BNZ   ERR1               BRANCH IF SIO NOT ACCEPTED       
 WAIT     TIO   0(R2)              WAIT FOR I/O COMPLETION          
          BZ    DUMP               GO DUMP RECORD                   
          BC    1,ERR2             BRANCH IF ERROR                  
          B     WAIT               KEEP WAITING...

By now this code should look pretty familiar.  We save the caller’s return address.  Next we store the address of our CCW program into the CAW and then issue the SIO.  We use TIO to wait for the I/O to complete.

DUMP     DS     0H                                                    
         MVC    CSW,64                 SAVE CSW FOR LATER             
         @PRINT '----- CSW ------'                                    
         @DUMP  CSW,10                                                
         @PRINT ' '                                                   
         @PRINT '-----DATA BUFFER-----'                               
         SLR    R3,R3                  ZERO R3                        
         ICM    R3,B'0011',CCWREAD+6   GET CCW DATA LENGTH            
         SLR    R1,R1                  ZERO R1                        
         ICM    R1,B'0011',CSW+6       GET RESIDUAL LENGTH            
         SR     R3,R1                  CALCULATE LENGTH READ          
         @DUMP  INBUF,(R3)                                            
         @PRINT ' '                                                   
         @PRINT ' '                                                   
         L     R14,DUMPRCXT       SAVE RETURN ADDRESS                 
         BR     R14               RETURN TO CALLER

After the DASD I/O is complete we save the CSW because it will be overwritten when we issue I/O to the printer.  We use our @DUMP macro to format the storage containing our saved CSW.

Next we get the residual length value from the CSW and subtract it from the length value in our read CCW.  This gives us the actual length of the data that was read.  (For example if we attempted to read 100 bytes of data and the residual length was 40 – we would have actually read 60 bytes of data).

We then format the contents of the I/O data buffer and then return to the caller.

         DS    0D                                                    
CCWSEEK  DC    X'07',AL3(MBBCCHHR+1),AL1(@CCW#CC),X'00',AL2(6)       
CCWSRCH  DC    X'31',AL3(MBBCCHHR+3),AL1(@CCW#CC),X'00',AL2(5)       
         DC    X'08',AL3(CCWSRCH),AL1(@CCW#CC),X'00',AL2(0)          
CCWREAD  DC    X'06',AL3(INBUF),AL1(@CCW#SLI),X'00',AL2(2048)        

Our CCW program begins with a Seek (x’07’).  It is followed by a Search ID Equal (x’31’) and a TIC (x’08) to search for the specific record we want to read.  Finally we use a Read Data (x’06’) to read the data area of the record.

We specify Command Chaining on all CCW’s except the last.  Our Read CCW has the SLI since we don’t expect our requested length to match the actual data length.

         DS    XL((((*-BEGIN+16)/16)*16)-(*-BEGIN))                  
CSW      DC    D'0'                                                  
*               +0+1+2+3+4+5+6+7                                     
*                 M B B C C H H R                                    
**********     X'0000000000000001'                                   
MBBCCHHR DS    0X                                                    
MBB      DC    X'000000'                                             
CCHHR    DS    0X                                                    
CC       DC    X'0000'                                               
HH       DC    X'0000'                                               
R        DC    X'01'                                                 

The strange looking DS XL statement is used to align the address to a multiple of 16 bytes.  We use a similar DS  to align the I/O buffer to an even multiple of 256 (so when we format the buffer the beginning address is XXXXX00).

          MVI   R,1                READ RECORD 1                 
          @PRINT '------- CC=00 HH=00 R=1 --------'              
          BAL   R14,DUMPREC                                      
          MVI   R,2                READ RECORD 2                 
          @PRINT '------- CC=00 HH=00 R=2 --------'              
          BAL   R14,DUMPREC

First we dump record R1 and R2 (IPL1 and IPL2)  Since the CCHH is already set to cylinder 0 and Head 0 all we have to do is specify the record number.

         MVI   R,3                READ RECORD 3                       
         @PRINT '------- CC=00 HH=00 R=2 --------'                    
         BAL   R14,DUMPREC                                            
         MVC   CCHHR(5),VTOCADDR  READ FIRST VTOC RECORD              
         @PRINT '------- VTOC FMT 4 DSCB --------'                    
         BAL   R14,DUMPREC

Next we read record 3 which is the volume label.  The CCHHR address of the VTOC is saved and then moved into our DASD block address MBBCCHHR area.  We can then read and dump the Format 4 DSCB data area.

[Next – DISK1 Assembly Listing]