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)