1CSCI 468 Spring, 2007 SOS-I/O R. P. Rannie Page 1 of 6
A major change here is that you will now use SIO coding (using CCWs) for most portions of the I/O. You will write the short channel programs needed to read or to write. Assist-V uses pseudo devices (via DDNAMEs) as the target for the SIO commands. These are the devices listed in the Assist-V JCL as 'VIRT' devices. The addresses of the two virtual card readers are 00C and 00D. The addresses of the two virtual printers are 00E and 00F. Another major change here will be Multi-Programming! (MAXI .GT. 1)
====: New Features of SVC 8 (Note: Use 'LOADER' - Check w/Inst.)
For SVC 8 use LOADERC which will issue SVC 0 reads in order to read from VIRT device 000C to load the object module test programs. (Continue to use LOADER until you get your SIO going.)
====: New Features of SVC 0
SVC 0 has previously been described in part. You now need to modify your test in SVC 0 to determine whether or not the IOBDEVAD field of the IOB (pointed to by R1 on entry to the SVC) is X'0000'. If this field is zero, then you will do an XREAD or XPRNT as you have done previously. If this field is NOT zeros, then you will branch (via R12) to the RQEENQ routine.
====: Unit Control Blocks (UCBs)
Set the 2K of memory at X'800' to a protection state of X'08'. Assemble UCBs for addresses X'000C' through X'000F' beginning at memory location X'800' (for X'000C'). The UCBs MUST be chained together and the UCB for X'000C' should be pointed to by the CVTUCBS. Assembled UCBs should be zero except for the fields UCB-IDENT, CHAN, UCB, NAME, and IOSTR. (See DSECT for logic.)
====: CVT
You will need to set up adcons for CHAP, BEGINIO, the 1ST-UCB, CVTUCBS, and RQEENQ. (See DSECT for these items.)
====: Changes to SVC 3
With this assignment you WILL need to perform the FRECB100 on some of the Request Blocks you 'kill'. Freeing the SVRBs but not the PRBs should provide you with an adequate supply of CB100s.
====: New Features of Dispatching (End Job Code and Trace Off/On)
At Job End, continue to print (XPRNT) the 'Job End' message that includes your name, the TCB and PROGRAM (from EPA+5) names, and job accounting information as follows. Dispatched Task Time (Problem State): TCBTCPUP. Dispatched Task Time (Supervisor State): TCBTCPUS. The sum of I/O Wait Times (measured from SIO w/CC=0 to Device End I/O Interrupt): TCBTWAIT. I/O Counts (1 byte/device, Count ONLY if SIO returned CC=0): TCBIOCNT. Note that bytes 0, 1, 2, and 3 in this field are for Device(s) 00C, 00D, 00E, and 00F.
Put a counter in your 'DODISP' code that will issue an XOPC 4 every dispatch AFTER your
dispatch count exceeds 'nn' (probably 60) to reduce trace volume. Modify or remove this
for debugging.
1CSCI 468 Spring, 2007
SOS-I/O
R. P. Rannie
Page 2 of 6
====: RQEENQ (Request Queue Element ENQueue routine)
On entry to RQEENQ you will test (LEVELABN if Ty-1 Flag .NE. 1) and set TO ZERO the TYP1FLAG. You do this because you will NOT be returning to the SVC-FLIH after performing the necessary operations in this module. Next you 'acquire' an RQE from the available stack of CB100s as you 'acquired' RB-s.
Clear ALL of the CB100 to X'00'! You fill in the information in the RQE that will be needed to start the requested I/O operation (sometime in the future), and then you add this RQE to the chain of RQEs that are attached to the Unit Control Block (UCB) that represents the device whose address was in the IOBDEVAD field of the IOB. These RQEs represent I/O requests that will be performed on the 'VIRT' devices using SIO and CCWs. Note that RQEs will eventually be freed, and put back on the stack of available CB100s (using FRECB100), by the I/O FLIH.
Another function of the RQEENQ routine is to make the RB that requested this I/O NON-dispatchable. This is done by performing a branch entry into SVC 1 using one (R0 = 1) ECB (cleared to zero and located in the RQE at RQEIOECB.) Remember that the program designated by the TCB/RB is not allowed to be run, that is, --to be dispatched-- until the RBWCF is zero (i.e., until the I/O operation is completed.) Note that this is like QSAM rather than BSAM.
The RBWCF will later be decremented in the I/O interrupt handler (via branch entry to SVC 2 using the ECB located in the RQE at RQEIOUCB) when I/O has completed. After Enqueuing the RQE you will branch (via R12) to the BEGINIO routine.
====: BEGINNING (Initiating) the I/O -- The BEGINIO Routine
You will come to BEGINIO via a BR R12 from EITHER (a) the RQEENQ routine ==:OR:== (b) the IOFLIH routine ==:OR:== (c) a UCB's STARTIO routine. Do NOT make the dreaded 'ASSUME' that CONDITIONS, POINTERS, and REGISTERS on entry from each of the locations are the same! It is YOUR responsibility to set up ALL THAT IS NECESSARY at the common entry point of the BEGINIO routine!
The function of the BEGINIO routine is to run the UCB chain (starting at the first UCB pointed to by the CVT) looking for UCBs which meet these criteria: (1) The device is NOT-busy, (2) There is an RQE chained off of the UCB (UCBWARQE) indicating a Waiting RQE containing an I/O request (the UCBWARQE field is NOT zero!), and (3) Verify that the UCBCURQE field of this UCB is zero! (XOPC 25 if not!),
If these criteria are met, then the BEGINIO routine should (a) DEQUEUE the 1st RQE in the UCBWARQE queue, (b) update the UCBWARQE field in the UCB with the contents of that 1st RQE's RQENRQE field, (c) now set that RQE's RQENRQE field to F'-1', (to avoid problems), (d) put the address of that 1st RQE into the UCBCURQE field, and (e) branch to the Start I/O (perform the actual SIO instruction) routine for that particular device (which is pointed to in the UCBIOSTR field of the UCB).
1CSCI 468 Spring, 2007 SOS-I/O R. P. Rannie Page 3 of 6
====: The BEGINIO Routine (Continued)
Return from each SIO routine should be to the ENTRY POINT of the BEGINIO routine. In effect, the BEGINIO process should be RESTARTED AT THE FIRST UCB. This should continue until the end of the UCB chain (indicated by zero in the UCBUCB chaining field) is reached. At this point, with no more I/O to start, BEGINIO will exit to the CHAP routine via BR R12 (address found in the CVT.)
====: The SIO Routine(s)
There needs to be a SIO routine for EACH device (each UCB). There also needs to be a SEPARATE CHANNEL PROGRAM for each SIO routine. For the readers this is a ONE CCW channel program that does a read of an 80 byte input record. (All input records for this assignment will be 80 byte records.) For the printers this is typically a TWO CCW channel program that does (1) a 'machine' (Not! ANSI) carriage control command for single, double, triple, or top of page spacing. This is followed (command chained) by (2) a channel command to write a line WITHOUT spacing.
Notice that if the carriage control command (ANSI) is a + (meaning 'do not advance the printer') then the channel program to be executed is only a ONE CCW program and the program begins (and ends) with only the SECOND (write a line without spacing) CCW! Remember, the SECOND CCW 'prints' from BUF+1 for a length of LEN-1.
Note: For a write command with a buffer length of 1, (carriage control ONLY), set the first CCW to perform the correct carriage control but turn OFF command chaining in that first CCW.
Each SIO routine will modify the its own CCWs in preparation for doing a store of the correct channel program address into the CAW followed by a SIO instruction followed by a testing of the CC set by that SIO. In printing, this routine will examine the user supplied carriage control character (ANSI: 1, blank, 0, -, or +) and convert that to the correct 'machine' control character (to be used in the 'carriage control' CCW). These are X'88', X'0B', X'13', and X'1B', with special processing needed for '+'.
You will need to handle 'top of page', single, double, triple, and NO space. You need to translate any other carriage control character to a default of single space.
All print buffers being processed via SIO coding must use a 133 byte buffer. For a print request, you should overlay a C'E' or C'F' into the rightmost print buffer location (BUF+132) of the buffer to be printed. This will identify the particular VIRTUAL printer to which this print command was sent. Since each TCB should have a unique name (number in TCB name, with 'M' and 'W' for MS/NIP and Wait), move the TCB-unique character from TCB Name+3 into BUF+131 to identify the source of the print line. Note: All system and test program output lines are length 133 (cc + 132).
The CAW that will be set in the SIO routine will have a key corresponding to the key of the area from which the CCWs will be obtained (fetched). Since these CCWs are in the system area, this key must be set to zero. The CSW that is stored will contain the key that was found in the CAW when the channel program was started.
1CSCI 468 Spring, 2007 SOS-I/O R. P. Rannie Page 4 of 6
====: The SIO Routine(s) (Continued)
It will be in the Start I/O routine where the results of testing the CC following the SIO instruction will be acted upon.
Before a SIO is issued the address of the start of the channel program must be loaded into the CAW. Then, as soon as you issue the SIO, you are at liberty to change the CAW because the channel will have already fetched the address of the start of the channel program. The SIO will return a condition code. See the POO and the Green Card.
If you get 3 (not operational) - check your device address and/or your JCL. If you get 2 (busy) or 1 (CSW Stored) you need to XOPC 25 and see what is wrong. You should not be starting I/O to a busy device. Check your flagging in the UCB! If you get a CC=0, all is well and the I/O is probably off and running. NOW (and ONLY NOW!) is when YOU SET the flag in the UCB to indicate the device is busy! It is at this time that you need to store the current time of the 'Start I/O' in the TCBTSSIO so that at the I/O Interrupt you will have an amount of 'Waiting for I/O to complete' time.
====: I/O Interrupt Handling Routine
We now introduce the I/O interrupt handler. To begin with, it performs all (timer,
save, etc.) the same 'good stuff' functions of any FLIH. Then it examines the I/O OLD PSW
and the CSW to determine the state of the I/O that just completed. First check the CSW
Unit and Channel Status (bits 32-47) for the occurrence of any 'bad' bits which would tell
you that the program should now be terminated XOPC 25. Normally, 'Bad' bits are ANY other
than Channel End, Control Unit End, Device End, Incorrect Length, and Unit Exception.
If no 'bad' bits are present, check to see if this was Device End. It may not be since up
to three 'end generating interrupts' may be received. These interrupts are Channel end,
Control Unit end, and Device end. Receiving multiple 'ends' is OK. They indicate
completion of various parts of the I/O operation. But you must have a DEVICE END interrupt
to show the operation is finally and totally complete; -- Otherwise you branch immediately
to CHAP!
The address of the device signaling the completion of the I/O is in the I/O OLD PSW
interrupt code field. This points you to the proper UCB.
Perform BRANCH entry to SVC 2 to decrement by one the RBWCF of the RB WHOSE ADDRESS IS IN
THE ECB that is in the RQEIOECB. Use a post code of X'7F',C'IOS' (Signifying 'I/O
Supervisor'.)
Mark the UCB for this device as NON-busy. Remove the RQE (pointed to by the UCBCURQE
field) from the UCB and put it back on the stack of free CBs. Clear the UCBCURQE to zero!
When this is done, branch to the BEGINNING of the BEGINIO routine (there may be devices
(UCBs) with waiting RQEs for which I/O should be started.)
Be sure and return the correct value in R15 to indicate the result of a Read or Write.
Write always returns RC=0 and Read returns RC=0 unless it got EOF, in which case RC=4. How
do you do this? You must test for 8C'9' in the input buffer defined in the IOB. In
non-I/O processing using SVC 0, this testing was performed in the SVC 0 module.
Remember that you will not be returning to the SVC 0 module, and setting of the proper
Return Code must be done while you are in the I/O Interrupt Handler - Supervisor.
1CSCI 468 Spring, 2007 SOS-I/O R. P. Rannie Page 5 of 6
====: JCL
In this assignment you will rerun a 'real I/O version' of previous SOS jobs using OBJMOD7I, 8I, 9I (twice), and NI, using your enhanced SOS which uses SIO (Channel Commands) to perform I/O. Note that you must arrange to have OBJMODNI run at X'D000'.
//* X'00C' IS VIRTRDR1 -- PARMS, (AND OBJ. MODS. WITH LOADERC!) //VIRTRDR1 DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM1111),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM2222),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM3333),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM4444),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(PARM7777),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR //* X'00D'IS VIRTRDR2 -- USER PROGRAM INPUT. //VIRTRDR2 DD DSN=SYS1.MACLIB(CHECK),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR // DD DSN=SYS1.MACLIB(EOV),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR // DD DSN=SYS1.MACLIB(NOTE),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR // DD DSN=SYS1.MACLIB(ERASE),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR // DD DSN=SYS1.MACLIB(EXCP),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(ALLNINES),DISP=SHR //* IN THIS CASE THERE IS NOT A REAL END OF FILE AFTER LAST DATA //VIRTPRT1 DD SYSOUT=*,DCB=(BLKSIZE=133,RECFM=FM,BUFNO=1) PRT 000E //VIRTPRT2 DD SYSOUT=*,DCB=(BLKSIZE=133,RECFM=FM,BUFNO=1) PRT 000F //*FT05F001 (USED AS INPUT ONLY FOR LOADER, NOT LOADERC=Uses 00C) //* Load programs starting at X'A000', etc. Note: OBJMODNI at D000! //FT05F001 DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMOD9I),DISP=SHR A000 // DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMOD8I),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMOD7I),DISP=SHR //* Note: OBJMODNI ==: MUST :== be loaded at X'D000'! // DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMODNI),DISP=SHR // DD DSN=T90RPR1.CS468PUB.OBJLIB(OBJMOD9I),DISP=SHR
Output from the test programs will be directed as follows: OBJMOD7I to X'000E', OBJMOD8I to X'000E', OBJMOD9I to X'000F', and OBJMODNI to X'000F', All test programs read PARMS from X'000C'. All programs will read input data from X'000D'. Job start messages from MS/NIP should go to 'E'. Job (TASK) end messages from Dispatcher End Job code should continue to be written using XPRNT. Messages from SVC 13 should go to 'F'.
====: CHAnge Priority (CHAP) Routine :=====
The CHAP routine is used to change the priority of TCBs in the TCB chain. The present assignment may not perform any priority change in CHAP. Upon entering CHAP (Base Register = 12) you will simply get the address of the Dispatcher (from the CVT) and branch (using R12) to the Dispatcher.
1CSCI 468 Spring, 2007 SOS-I/O R. P. Rannie Page 6 of 6
====: Misc.
Notice that the RBs are attached to the TCB as a 'stack'. They are put on at one end and taken off at the SAME end. In the case of the RQEs that are attached to the UCB this is a 'queue'. They are put on at one end and taken off at the OTHER end. Write your code accordingly.
Use the 4th of your 'register save areas' in low core at X'1C0' for the I/O save area. Do NOT use a '5th area' at X'200'! This could overlay control blocks located in this area!
Hard code your SIOs. e.g. SIO X'00D' -- so the trace will show ======: 9C00000D (showing WHICH device was the target of the SIO!)
BEWARE! Print buffers that cross 2K boundaries will have ALTERED! outputs beyond the boundary! ORG accordingly to avoid Buffer Boundary Crossing!
The following code (using the HLASMC) will be used at this time. Use the CPARM=RENT
parameter of the assembler to assure that you have a Reentrant SVC 13 module. Note that
you will need to have a Reentrant SVC 13 when you run your SOS-I/O using MULTIprogramming!
(MAXI .GT. 1)
And your SVC13 HLASMC JCL will now include: CPARM=RENT and
SVC13 START X'Address in SOS of your SVC 13 module' (NOT CSECT)
//ASM.SYSLIB DD
//
DD
//
DD DSN=T90RPR1.CS468PUB.MACLIB,DISP=SHR
//ASM.SYSLIN DD DSN=&&OSVC13(SVC13),SPACE=(6160,(1,1,1)),
//
DCB=(LRECL=80,RECFM=FB) 'DCB' MUST BEGIN IN COL. 16
And your ASSISTV JCL will now include:
//* X'00C' IS VIRTRDR1 -- SVC 13, PARMS, AND OBJ. MODS.
//VIRTRDR1 DD DSN=&&OSVC13(SVC13),DISP=(OLD,DELETE) ====:
Where &&OSVC13 is the first in a
concatenation of 6 DDs :====
In NIP you will LOAD your assembled (via HLASMC) Object Module of SVC 13 into the designated (and padded with C'6') area in your SOS. The address of this area is the same as the address that you provided to the START at the beginning of the assembly of your SVC 13. It is also the same as the address of your SVC 13 module specified in your SVC Table.
The SOS loaders (including the one you wrote) can LOAD an OM that contains A-Cons when the assembled address (via START) is the same as the target address of the loader. NOTE: The SOS loaders can N-O-T handle V-Cons!