Now that we have successfully managed to read from a DASD device we can build a general purpose subroutine to perform I/O. We will create a control block to communicate with the I/O routine. The control block will be called I/O Request (IOR).
IOR DSECT , IORCCW DS A ADDRESS OF CCW IORUNIT DS XL2 DEVICE ADDRESS IORSIOCC DS X SIO CONDITION CODE DS X IORCSW DS XL8 CHANNEL STATUS WORD IORSENS0 DS X SENSE BYTE 0 IORSENS1 DS X SENSE BYTE 1 * IORLEN EQU *-IOR
The first two fields are input to the I/O routine and the remainder are output. The IORCC field points to the CCW chain to execute. The IORUNIT field contains the device address. IORSIOCC returns the condition code returned form the SIO instruction. IORCSW contains a copy of the CSW after the I/O request is complete. If the I/O operation resulted in a Unit Check condition the I/O subroutine will perform a sense command and save the first two bytes into IORSENS0 and IORSENS1.
The I/O subroutine returns a completion code in Register 15 to indicate the completion status of the I/O request.
- RC = 0 – The I/O Completed Normally
- RC = 4 – Exceptional Condition Encountered
- RC = 8 – I/O Not Initiated (SIO CC Stored)
- RC = 16 – TIO Error
********************************************************************** * XIO - PERFORM I/O SUBROUTINE * R1 = A(IOR) I/O REQUEST BLOCK * ON EXIT R15 CONTAINS A RETURN CODE ********************************************************************** * XIO DS 0H STM R14,R12,12(R13) SAVE CALLER'S REGISTERS LA R14,XIOSAVE POINT TO OUR SAVE ADDRESS ST R14,8(,R13) ST R13,4(,R14) LR R13,R14 * LR R10,R1 IOR BLOCK ADDRESS USING IOR,R10 *
We begin by saving the callers registers and then establishing a new save area. The IOR address is copied into Register 10 and mapped against the IOR DSECT.
XC IORSIOCC,IORSIOCC XC IORSENS0(2),IORSENS0 XC IORCSW,IORCSW
First the output fields in the IOR are cleared.
L R1,IORCCW POINT TO CCW CHAIN ST R1,72 SAVE INTO CAW SLR R2,R2 ICM R2,B'0011',IORUNIT DEVICE ADDRESS SIO 0(R2) START I/O BC 4,SIOCC4 BRANCH IF SIO NOT ACCEPTED BC 2,SIOCC2 BRANCH IF SIO NOT ACCEPTED BC 1,SIOCC1 BRANCH IF SIO NOT ACCEPTED
The CCW address is saved into the CAW and a SIO is issued against the device. If the SIO did not complete with CC=8 a SIO CC code is stored in the IOR and the return code is set to 8.
WAITIO TIO 0(R2) WAIT FOR I/O COMPLETION BC 1,TIOCC1 BRANCH IF ERROR BC 7,WAITIO KEEP WAITING... * MVC IORCSW,64 SAVE CSW CLC =X'0C00',ORCSW+4 CHANNEL END/DEVICE END BE WAITIO20 YES - GOOD COMPLETION TM IORCSW+4,X'02' UNIT CHECK? BNO WAITIO15 NO - DON'T NEED TO SO SENSE
A TIO loop is executed to wait for the I/O request to complete. Once the I/O has completed the CSW copied into the IOR. If any status bits except Channel End and Device End are set it is considered to be an exceptional condition.
If Unit Check was set we fall through to issue a sense command.
LA R1,CCWSENSE ST R1,72 SAVE INTO CAW SIO 0(R2) START I/O BC 7,WAITIO99 ERROR * WAITIO10 TIO 0(R2) WAIT FOR I/O COMPLETION BC 1,WAITIO99 BRANCH IF ERROR BC 7,WAITIO10 KEEP WAITING... * MVC IORSENS0(2),SENSE SAVE SENSE BYTES 0 & 1 WAITIO15 DS 0H WAIT FOR I/O COMPLETION LA R15,4 SET RC=4 B XIOXT
The address of the SENSE CCW is stored into the CAW and a SIO is issued to the device. A TIO loop is used to wait for the Sense I/O to complete. The first two bytes of the sense data is stored into the IOR. We can now exit with a return code of 4.
SIOCC1 DS 0H MVI IORSIOCC,X'01' LA R15,8 B XIOXT * * SIOCC2 DS 0H MVI IORSIOCC,X'02' LA R15,8 B XIOXT * * SIOCC4 DS 0H MVI IORSIOCC,X'04' LA R15,8 B XIOXT * * WAITIO99 DS 0H TIOCC1 DS 0H LA R15,16 B XIOXT * * XIOXT DS 0H L R1,4(,R13) ST R15,16(,R1) * @PRINT '-------- IOR --------' @DUMP IORB,IORLEN @PRINT ' ' @PRINT ' ' * L R13,4(,R13) LM R14,R12,12(R13) RESTORE CALLER'S REGS BR R14 RETURN TO CALLER
We finally end up at XIOXT with a return code set in Register 15. Here I save the RC into the callers save area so it will be restored into Register 15 before returning to the caller. For debugging purposes I have included a dump of the IOR Block. (This is why saving the value in Register 15 was necessary)