IOM TITLE 'DMTIOM (RSCS) VM/370 - RELEASE 6' 00001000
*. 00002000
* MODULE NAME - 00003000
* 00004000
* DMTIOM 00005000
* 00006000
* FUNCTION - 00007000
* 00008000
* THE DMTIOM MODULE CONTAINS BOTH THE MSUP I/O 00009000
* INTERRUPT HANDLER AND THE TASK I/O SERVICE 00010000
* ROUTINE. THE I/O SERVICE PROVIDED BY DMTIOM TO THE 00011000
* TASK PROGRAMS INCLUDES SEQUENTIAL SUBCHANNEL 00012000
* SCHEDULING, CHANNEL PROGRAM EXECUTION, AUTOMATIC 00013000
* SENSE EXECUTION ON UNIT CHECK WHEN REQUESTED, 00014000
* RETURN OF ALL PERTINENT INFORMATION REGARDING THE 00015000
* EXECUTION OF THE CHANNEL PROGRAM, AND NOTIFICATION 00016000
* VIA POST ON COMPLETION OF CHANNEL PROGRAM 00017000
* EXECUTION. 00018000
* 00019000
* ATTRIBUTES - 00020000
* 00021000
* REUSABLE 00022000
* 00023000
* INTERRUPT ENTRY EXECUTABLE DISABLED ONLY 00024000
* 00025000
* ENTRY POINTS - 00026000
* 00027000
* DMTIOMIN - DIRECTLY ON I/O INTERRUPT 00028000
* DMTIOMRQ - ON I/O SERVICE REQUEST FROM DISPATCHED PROGRAM 00029000
* 00030000
* 00031000
* ENTRY CONDITIONS - 00032000
* 00033000
* ON INTERRUPT ENTRY, THE I/O STATUS INFORMATION IS STORED 00034000
* IN THE I/O OLD PSW AND THE CSW. ENTRY MAY OCCUR AT ANY 00035000
* TIME AN I/O SYSTEM MASK IS ON. 00036000
* 00037000
* ON TASK SERVICE CALL ENTRY, GREG 1 POINTS TO THE TASK'S 00038000
* I/O REQUEST TABLE. 00039000
* 00040000
* 00041000
* EXIT CONDITIONS - 00042000
* 00043000
* NORMAL - 00044000
* 00045000
* UNDISPATCHED, TO THE DISPATCHER TO RESUME PROCESSING. 00046000
* 00047000
* ERROR POST CODES - 00048000
* 00049000
* 2,3 = SIO CONDITION CODES 00050000
* 8 = AUTO SENSE FAILED - NO FREE SUP QUEUE ELEMENT 00051000
* 12 = AUTO SENSE FAILED - I/O ERROR 00052000
* 16 = I/O REQ FAILED - NO FREE SUP QUEUE ELEMENT 00053000
* 00054000
* 00055000
EJECT 00056000
* 00057000
* CALLS TO OTHER ROUTINES - 00058000
* 00059000
* DMTQRQ - TO RESERVE OR RELEASE SUPERVISOR QUEUE ELEMENTS 00060000
* DMTDSP - TO RESUME DISPATCHED PROCESSING 00061000
* 00062000
* 00063000
* EXTERNAL REFERENCES - 00064000
* 00065000
* NONE 00066000
* 00067000
* 00068000
* TABLES / WORKAREAS - 00069000
* 00070000
* TAREA - TASK SAVE AREA 00071000
* TASKE - TASK SUPERVISOR QUEUE ELEMENT 00072000
* IOE - I/O REQUEST SUPERVISOR QUEUE ELEMENT 00073000
* ASYNE - ASYNCH I. 00074000
* ASYNE - ASYN I/O IRRPT EXIT REQ SUP QUEUE ELEMENT 00075000
* IOTABLE - TASK I/O REQUEST TABLE 00076000
* 00077000
* 00078000
* 00079000
* REGISTER USAGE - 00080000
* 00081000
* GPR0 = RETURN POST CODE ON ENTRY TO DISMISS 00082000
* GPR1 = PARAMETER PASSING REGISTER 00083000
* GPR2 = I/O REQUEST ELEMENT BASE 00084000
* GPR3 = I/O TABLE BASE, OR AUTO SENSE ELEMENT BASE 00085000
* GPR4 = ADDR OF PREDECESSOR ELEM OF GPR2 I/O ELEM 00086000
* GPR5 = I/O QUEUE SCAN ELEMENT POINTER REGISTER 00087000
* GPR12 = DMTIOM BASE REGISTER 00088000
* GPR14 = TASK AREA BASE REG; LINKAGE RETURN REG 00089000
* GPR15 = LINKAGE ENTRY REG 00090000
* 00091000
* NOTES - 00092000
* 00093000
* ASSUMPTIONS USED BY DMTIOM LOGIC: 00094000
* 00095000
* 1. FOLLOWING SIO, CC=0, FOR A CERTAIN DEVICE ADDRESS, 00096000
* THE FIRST I/O INTERRUPT SPECIFYING THAT DEVICE ADDRESS, 00097000
* AND SPECIFYING STATUS OTHER THAN STANDALONE PCI, 00098000
* SIGNALS CHANNEL TERMINATION AND THE PRESENCE OF VALID 00099000
* ENDING CCW ADDRESS AND RESIDUAL COUNT. 00100000
* 00101000
* 2. FOR THE PURPOSES OF MULTIPLEXOR CHANNEL SCHEDULING, 00102000
* DEVICE ADDRESSES X'000' TO X'0BF' ARE EACH ON NON- 00103000
* SHARED SUBCHANNELS; DEVICE ADDRESSES X'0C0' TO X'0CF', 00104000
* X'0D0' TO X'0DF', X'0E0' TO X'0EF', AND X'0F0' TO 00105000
* X'0FF' ARE ON SUBCHANNELS SHARED WITHIN THE GROUP 00106000
* OF ADDRESSES IN WHICH THE DEVICE ADDRESS RESIDES. 00107000
* 00108000
EJECT 00109000
* 00110000
* OPERATION - 00111000
* 00112000
* 00113000
* THE I/O SERVICE ROUTINE IS ENTERED VIA A BRANCH 00114000
* AND LINK FROM TASK PROGRAMS. EXECUTION OF THE 00115000
* CALLING TASK IS IMMEDIATELY SUSPENDED BY MEANS OF 00116000
* THE FREEZE SVC. A SUPERVISOR QUEUE ELEMENT IS 00117000
* GOTTEN BY MEANS OF A CALL TO DMTQRQ, AND THE 00118000
* APPROPRIATE I/O ELEMENT IS BUILT USING THE 00119000
* INFORMATION SPECIFIED IN THE I/O REQUEST TABLE 00120000
* SUPPLIED BY THE CALLER. THE APPROPRIATE (SELECTOR 00121000
* OR MULTIPLEXOR) CHANNEL QUEUE IS SCANNED TO LOCATE 00122000
* THE POSITION OF THE SUBQUEUE FOR THE SUBCHANNEL ON 00123000
* WHICH THE I/O IS TO BE EXECUTED. IF A SUBQUEUE 00124000
* ALREADY EXISTS FOR THE SUBCHANNEL, THE IMPLICATION 00125000
* IS THAT THE SUBCHANNEL IS BUSY WITH ANOTHER I/O 00126000
* REQUEST EXECUTION. IN THIS CASE, THE NEW REQUEST 00127000
* ELEMENT IS ENQUEUED AT THE END OF THE SUBQUEUE FOR 00128000
* LATER EXECUTION, AND CONTROL IS PASSED TO THE 00129000
* DISPATCHER. IF NO SUBQUEUE EXISTS, THE NEW ELEMENT 00130000
* BECOMES THE FIRST ENTRY IN THE SUBQUEUE AND 00131000
* CONTROL IS PASSED TO THE ROUTINE WHICH STARTS I/O 00132000
* REQUEST ELEMENTS. 00133000
* 00134000
* ON ENTRY FROM AN I/O INTERRUPT, DMTIOMIN SAVES THE 00135000
* EXECUTION STATUS IF NECESSARY AND SEARCHES THE 00136000
* APPROPRIATE I/O QUEUE TO FIND AN ACTIVE I/O 00137000
* REQUEST ELEMENT ON THE INTERRUPTING DEVICE. IF NO 00138000
* SUCH ELEMENT IS FOUND, THE ASYNCHRONOUS I/O EXIT 00139000
* QUEUE IS SCANNED FOR A MATCHING DEVICE ADDRESS, 00140000
* AND AN ASYNCHRONOUS EXIT IS TAKEN IF A MATCH IS 00141000
* FOUND. IF NEITHER AN ACTIVE I/O REQUEST ELEMENT 00142000
* NOR AN ASYNCHRONOUS EXIT REQUEST ELEMENT IS 00143000
* LOCATED FOR THE INTERRUPTING DEVICE, THE INTERRUPT 00144000
* IS IGNORED AND CONTROL IS PASSED TO THE 00145000
* DISPATCHER. 00146000
* 00147000
* IF AN ACTIVE I/O ELEMENT IS FOUND, THE ELEMENT AND 00148000
* THE ASSOCIATED I/O REQUEST TABLE IN TASK STORAGE 00149000
* ARE UPDATED TO REFLECT THE NEW STATUS OF THE I/O 00150000
* REQUEST EXECUTION. IF THE INTERRUPT IS A STAND 00151000
* ALONE PCI, THE ASYNCHRONOUS EXIT REQUEST QUEUE IS 00152000
* SCANNED FOR A MATCHING DEVICE ADDRESS, AND THE 00153000
* EXIT IS TAKEN IF ONE IS FOUND. THE UPDATED ACTIVE 00154000
* I/O REQUEST TABLE IS INSPECTED TO SEE IF THE 00155000
* REQUESTED I/O PROCESSING HAS COMPLETED. IF IT HAS 00156000
* NOT, CONTROL IS IMMEDIATELY RETURNED TO THE 00157000
* DISPATCHER. OTHERWISE, THE I/O REQUEST TABLE IS 00158000
* INSPECTED TO SEE IF UNIT CHECK HAS BEEN SET AND 00159000
* AUTOMATIC SENSE HAS BEEN REQUESTED. IF THIS IS THE 00160000
* CASE, ANOTHER SUPERVISOR QUEUE ELEMENT IS GOTTEN 00161000
* BY MEANS OF A CALL TO DMTQRQ, THE SENSE CHANNEL 00162000
* PROGRAM IS BUILT IN THE NEW ELEMENT, THE NEW 00163000
* ELEMENT IS CHAINED TO THE REQUEST ELEMENT, AND THE 00164000
* SENSE OPERATION IS STARTED. IF THE SENSE OPERATION 00165000
* DOES NOT IMMEDIATELY COMPLETE, CONTROL IS PASSED 00166000
* TO THE DISPATCHER. 00167000
* 00168000
* WHEN SERVICE FOR A REQUEST IS COMPLETELY FINISHED, 00169000
* THE ASSOCIATED I/O ELEMENT (AND SENSE ELEMENT, IF 00170000
* PRESENT) ARE DEQUEUED AND FREED BY MEANS OF A CALL 00171000
* TO DMTQRQ, AND THE REQUESTING TASK'S I/O REQUEST 00172000
* TABLE IS POSTED BY MEANS OF A CALL TO DMTPST. IF 00173000
* ANOTHER I/O REQUEST ELEMENT IS PENDING ON THE 00174000
* SUBQUEUE FOR THE SUBCHANNEL WHICH HAS JUST 00175000
* COMPLETED THE PREVIOUS REQUEST EXECUTION, CONTROL 00176000
* IS PASSED TO THE ROUTINE WHICH STARTS I/O REQUEST 00177000
* ELEMENTS. OTHERWISE, CONTROL IS PASSED TO THE 00178000
* DISPATCHER. 00179000
* 00180000
* THE ROUTINE WHICH STARTS I/O REQUEST ELEMENTS MAY 00181000
* BE ENTERED EITHER FROM I/O INTERRUPT PROCESSING OR 00182000
* I/O REQUEST SERVICE. ITS FUNCTION IS SIMPLY TO 00183000
* MOVE THE STARTING CCW ADDRESS FROM THE TASK'S I/O 00184000
* REQUEST TABLE TO THE LOW STORAGE CAW, AND START 00185000
* THE I/O CHANNEL PROGRAM ON THE APPROPRIATE DEVICE. 00186000
* IF THE I/O COMPLETES IMMEDIATELY, CONTROL IS 00187000
* PASSED DIRECTLY TO THE ROUTINE WHICH COMPLETES I/O 00188000
* REQUEST PROCESSING AND SELECTS A NEW REQUEST ON 00189000
* THE SUBCHANNEL FOR PROCESSING. IF A PENDING 00190000
* ASYNCHRONOUS INTERRUPT FOR THE DEVICE IS CLEARED 00191000
* BY THE SIO, THE ROUTINE SETS A REGISTER WHICH 00192000
* CAUSES THE INTERRUPT TO BE FAKED PRIOR TO RETURN 00193000
* TO THE DISPATCHER. 00194000
* 00195000
* 00196000
*. 00197000
EJECT 00198000
DMTIOM CSECT 00199000
ENTRY DMTIOMIN,DMTIOMRQ 00200000
SPACE 00201000
*---------------------------------------------------------------------* 00202000
* * 00203000
* NOTE - THIS ROUTINE EMPLOYS THE FOLLOWING REGISTER USAGE: * 00204000
* * 00205000
* REG 2 = ADDRESS OF THE I/O REQUEST ELEMENT BEING PROCESSED * 00206000
* REG 3 = ADDRESS OF THE I/O TABLE ASSOCIATED WITH THAT ELEMENT* 00207000
* (OR, WHEN A SENSE ELEMENT IS PRESENT, THE ADDRESS OF * 00208000
* THAT SENSE ELEMENT) * 00209000
* REG 4 = ADDRESS OF THE I/O REQUEST ELEMENT WHICH POINTS TO * 00210000
* THE ELEMENT BEING PROCESSED (THE "LAST" ELEMENT) * 00211000
* * 00212000
* MODIFICATIONS WHICH WOULD USE THESE REGISTERS FOR OTHER * 00213000
* PURPOSES OUGHT TO BE MADE WITH A GREAT DEAL OF CAUTION * 00214000
* A WORD TO THE WISE .... * 00215000
* * 00216000
*---------------------------------------------------------------------* 00217000
SPACE 2 00218000
* I/O INTERRUPT ENTRY POINT 00219000
DMTIOMIN EQU * 00220000
SPACE 00221000
USING SVECTORS,0 GET SVECTORS ADDRESSABILITY 00222000
STM R14,R15,SSAVE SAVE WORK REGISTERS IN TEMPORARY SAVE AREA 00223000
L R15,NEWIO+4 REG 15 = ADDRESS OF I/O INTERRUPT ENTRY POIN 00224000
USING DMTIOMIN,R15 DEFINE TEMPORARY I/O SUPERVISOR ADDR 00225000
CLI ACTIVE,X'00' WAS THE DISPATCHER WAITING? 00226000
BE IONOSAVE YEP - SKIP SAVING REGISTERS 00227000
SPACE 00228000
L R14,ACTIVE REG.14 = ADDRESS OF ACTIVE TASK ELEMENT 00229000
L R14,TASKSAVE-TASKE(R14) REG 14 = ACTIVE TASK'S SUP SAVE 00230000
USING TAREA,R14 DEFINE TASK SAVE AREA DSECT ADDRESSA 00231000
SPACE 00232000
MVC TPSW(8),OLDIO SAVE INTERRUPTED PSW FOR RESUME 00233000
STM R0,R13,TGREG0 SAVE TASK'S GENERAL REGS 0->13 00234000
MVC TGREG14(8),SSAVE AND MOVE IN SAVED REGS 14 & 15 00235000
MVI ACTIVE,X'00' INDICATE DISPATCHER WAIT 00236000
SPACE 00237000
DROP R14 00238000
SPACE 00239000
IONOSAVE EQU * 00240000
LR R12,R15 REG.12 = PERMANENT BASE REGISTER 00241000
DROP R15 REG.15 MUST BE USED FOR CALLS LATER 00242000
USING DMTIOM,R12 DEFINE PERMANENT I/O SUP ADDRESSABIL 00243000
SPACE 00244000
CLI OLDIO+2,X'00' IS IT A SELECTOR CHANNEL INTERRUPT? 00245000
BNE IOSELCTR ABSOLUTELY - LOOK ON THE SELECTOR QUEUE 00246000
TM OLDIO+3,X'C0' IS IT MAYBE A SELECTOR SUBCHANNEL INTRPT? 00247000
BO IOSELCTR YEP - LOOK ON THE SELECTOR QUEUE FOR IT 00248000
L R2,MPXIOQ OTHERWISE REG.2 = START OF MULTIPLEXOR QUEUE 00249000
LA R4,MPXIOQ-(IONEXT-IOE) TRICKY START FOR QUEUE SEARCH LOO 00250000
B IOSEARCH GO LOOK FOR A MATCHING ACTIVE ELEMENT 00251000
EJECT 00252000
IOSELCTR EQU * 00253000
USING IOE,R2 GET I/O ELEMENT ADDRESSABILITY 00254000
USING IOTABLE,R3 GET IOTABLE ADDRESSABILITY 00255000
L R2,SELIOQ REG 2 = STARTING ADDRESS OF THE SELECTOR QUEUE 00256000
LA R4,SELIOQ-(IONEXT-IOE) INITIALIZE THE LAST ELEMENT POINT 00257000
IOSEARCH EQU * 00258000
LTR R2,R2 HAVE WE REACHED THE END OF THE ACTIVE QUEUE? 00259000
BZ IOASYNCH YEP - ACTIVE ELEMENT NOT FOUND 00260000
CLC OLDIO+2(2),IOADDR IS THIS THE APPROPRIATE ELEMENT? 00261000
BE IOFOUND YES - GO CHECK IT OUT 00262000
LR R4,R2 OTHERWISE SAVE ADDRESS OF THIS ELEMENT 00263000
L R2,IONEXT AND GET THE ADDRESS OF THE NEXT ELEMENT 00264000
B IOSEARCH AND KEEP LOOKING FOR ASSOCIATED ACTIVE ELEMENT 00265000
IOFOUND EQU * 00266000
L R3,IOTABLEA REG.3 = I/O TABLE ADDR (OR SENSE ELEMENT 00267000
SR R0,R0 CLEAR POST CODE 00268000
TM IOSTAT,SENSING IS AUTO SENSE ACTIVE FOR THIS ELEMENT 00269000
BNO IONOSENS NO - TASK'S I/O IS STILL ACTIVE 00270000
TM CSW+4,DE IS SENSE OPERATION ALL DONE? 00271000
BO IODISMIS YEP - POST THE REQUESTOR AND FREE EVERYTHING 00272000
B IODISPCH OTHERWISE JUST WAIT AROUND FOR A WHILE... 00273000
EJECT 00274000
IONOSENS EQU * 00275000
OC ENDCSW+4(2),CSW+4 OR NEW STATUS INTO TASK'S TABLE 00276000
CLC CSW+4(2),=AL1(0,PCI) IS IT PCI ALONE? 00277000
BE IOASYNCH YEP - PASS CONTROL TO TASK'S EXIT IF REQUESTED 00278000
TM IOSTAT,CHANDONE DID THE CHANNEL PREVIOUSLY TERMINATE? 00279000
BO IOCHKDEV YES - SEE IF DEVICE IS STILL ACTIVE 00280000
* 00281000
* ASSUMPTION: FIRST IRPT FROM ACTIVE WHICH IS 00282000
* NOT STANDALONE PCI SIGNALS 00283000
* CHANNEL TERMINATION 00284000
* 00285000
OI IOSTAT,CHANDONE SET FLAG TO INDICATE CHANNEL TERM 00286000
MVC ENDCSW+1(3),CSW+1 MOVE FINAL CSW ADDR TO I/O TABLE 00287000
MVC ENDCSW+6(2),CSW+6 MOVE IN FINAL CSW RESIDUAL COUNT 00288000
IOCHKDEV EQU * 00289000
TM ENDCSW+4,CE+DE IS CHANNEL END SET WITHOUT DEVICE END 00290000
BM IODISPCH IF SO, DEVICE END SHOULD BE COMING... (?) 00291000
TM ENDCSW+4,UC DEVICE IS DONE - IS UNIT CHECK SET? 00292000
BO IOUNITCK GO INVESTIGATE AUTO SENSE IF IT IS 00293000
EJECT 00294000
IODISMIS EQU * 00295000
TM IOSTAT,SENSING DOES FINISHED ELEMENT HAVE AUTO SENSE 00296000
BNO IONORMAL NOPE - DON'T NEED TO FREE SENSE ELEMENT 00297000
LR R1,R3 SET SENSE ELEMENT ADDRESS FOR QUEUE FREE 00298000
L R3,IOTABLEA-IOE(R3) REG 3 = ADDRESS OF TASK I/O TABLE 00299000
L R15,QREQ REG.15 = ENTRY ADDRESS FOR SUP QUEUE REQUESTS 00300000
BALR R14,R15 CALL DMTQRQ TO FREE THE OLD SENSE ELEMENT 00301000
IONORMAL EQU * 00302000
LA R1,IOSYNCH REG.1 = ADDRESS OF I/O REQUEST'S SYNCH LO 00303000
* REG.0 POST CODE SET ON ENTRY 00304000
L R15,POSTREQ REG.15 = ENTRY ADDRESS FOR POST ROUTINE 00305000
BALR R14,R15 CALL SYNCH ROUTINE TO POST TASK'S SYNCH LOCK 00306000
LR R1,R2 REG.1 = ADDRESS OF OLD TASK ELEMENT 00307000
L R5,IONEXT SAVE ADDRESS OF NEXT ELEMENT IN REG.5 00308000
L R2,IOSUBQ REG.2 = ADDRESS OF INACTIVE SUBQ ELEMENT 00309000
L R15,QREQ REG 15 = ADDRESS OF ENTRY FOR SUP QUEUE REQUEST 00310000
BALR R14,R15 FREE THE COMPLETED I/O REQUEST ELEMENT 00311000
LTR R2,R2 IS THERE AN INACTIVE ELEMENT FOR THIS SUB-CHANNEL? 00312000
BNZ IORSTART YES - GO RESTART THE CHANNEL 00313000
ST R5,0(R4) OTHERWISE CHAIN LAST ELEMENT TO NEXT 00314000
IOGO EQU * 00315000
CLI IOFAKE,X'00' ARE WE SET UP TO FAKE AN ASYNCH INTERRUPT? 00316000
BNE IOFAKEON YEP - GOTTA GO DO IT 00317000
IODISPCH EQU * 00318000
L R15,DISPATCH REG.15 = ENTRY POINT FOR NEXT DISPATCH 00319000
BALR R14,R15 EXIT TO SOME TASK THROUGH THE DISPATCHER 00320000
EJECT 00321000
IORSTART EQU * 00322000
ST R2,0(R4) CHAIN LAST ACTIVE ELEMENT TO THE NEW ONE 00323000
ST R5,IONEXT AND CHAIN THE NEW ELEMENT TO THE NEXT 00324000
L R3,IOTABLEA REG.3 = ADDRESS OF NEW TASK I/O TABLE 00325000
SPACE 00326000
IOSTART EQU * 00327000
XC CSW(8),CSW CLEAR THE CSW IN LOW CORE 00328000
MVI CAW,X'00' SET PROTECTION KEY TO ZERO IN THE CAW 00329000
MVC CAW+1(3),PROGADDR+1 SET CHAN PROG ADDR FROM I/O TABL 00330000
LH R1,IOADDR REG.1 = DEVICE ADDRESS FOR SIO 00331000
IOSIO EQU * 00332000
MVI SIOCOND,X'00' CLEAR I/O TABLE SIO COND CODE FIELD 00333000
SIO 0(R1) START UP THE I/O AND SEE WHAT HAPPENS... 00334000
BC 8,IOGO ALL DONE IF CHANNEL IS RUNNING 00335000
BALR R0,0 REG.0 = RIGHT HALF OF RUNNING PSW 00336000
SLL R0,2 SHIFT OFF THE INSTRUCTION LENGTH CODE 00337000
SRL R0,30 RIGHT JUSTIFY THE CONDITION CODE 00338000
STC R0,SIOCOND STORE THE SIO COND CODE IN IO TABLE 00339000
* POST CODE SAME AS CONDITION CODE FOR CC=2,3 00340000
BC 3,IONORMAL IF COND CODE = 2 OR 3, CONSIDER I/O FINISHED 00341000
TM CSW+4,SM+BUSY OTHERWISE COND CODE = 1 -- IS BUSY STAT SE 00342000
BNM IOFINIS NOPE - MUST BE IMMEDIATE OP OR ERROR(S) 00343000
TM CSW+4,X'AF' ANYTHING ELSE SET (BESIDES STATUS MODIFIER)? 00344000
BNZ IOFAKSET IF SO, WE HAVE CLOBBERED AN ASYNCHRONOUS INTRPT 00345000
IOFINIS EQU * 00346000
OI IOSTAT,CHANDONE SET CHANNEL TERMINATE FLAG 00347000
MVC ENDCSW+4(2),CSW+4 I/O COMPLETE - MOVE STAT TO I/O TAB 00348000
TM CSW+4,CE+DE IS CHANNEL END SET WITHOUT DEVICE END? 00349000
BM IOGO DON'T DISMISS THE ELEMENT IF DEVICE END IS COMING 00350000
SR R0,R0 CLEAR OUT R0 00351000
TM CSW+4,UC IS UNIT CHECK STATUS SET? 00352000
BNO IONORMAL ALL FINISHED WITH ELEMENT IF NOT 00353000
EJECT 00354000
IOUNITCK EQU * 00355000
SR R0,R0 CLEAR FOR EXIT TO IONORMAL 00356000
CLI SENSREQ,X'00' IS THERE A REQUEST FOR AUTO SENSE? 00357000
BE IONORMAL ALL DONE WITH ELEMENT IF NOT 00358000
SR R1,R1 CLEAR REG.1 FOR QUEUE GET REQUEST 00359000
L R15,QREQ REG.15 = ADDRESS OF QUEUE MANAGER CALL ENTRY 00360000
BALR R14,R15 GET A FREE ELEMENT TO SET UP SENSE OPERATION 00361000
LTR R15,R15 DID IT WORK? 00362000
LA R0,8 ERROR CODE IN CASE 00363000
BNZ IONORMAL NOPE - DMTIOM FLAGS IT 00364000
MVI IOSTAT-IOE(R1),X'00' CLEAR STATUS BYTE IN THE NEW ELEMEN 00365000
MVC IOTABLEA-IOE+1(3,R1),IOTABLEA+1 SET NEW ELEMNT I/O TAB 00366000
OI IOSTAT,SENSING SET SENSE FLAG IN ACTIVE ELEMENT 00367000
IC R0,IOSTAT SAVE THE REMAINING STATUS FOR THAT ELEMEN 00368000
ST R1,IOTABLEA SET ADDR OF SENSE ELEMENT IN ACTIVE ELEME 00369000
STC R0,IOSTAT AND RESTORE THE ACTIVE ELEMENT STATU 00370000
LA R0,ENDSENSE REG.0 = ADDR OF SENSE BUFFER IN I/O TABL 00371000
ST R0,0(R1) STORE BUFFER ADDRESS IN CCW AREA 00372000
MVI 0(R1),X'04' SET SENSE OP CODE IN NEW CCW 00373000
XC 4(3,R1),4(R1) CLEAR BYTES 4 -> 6 OF THE SENSE CCW 00374000
MVC 7(1,R1),SENSREQ MOVE REQUESTED SENSE BYTE COUNT TO C 00375000
LA R1,0(R1) CLEAR HIGH ORDER BYTE OF SENSE ELEMENT ADDR 00376000
ST R1,CAW AND SET THE ADDRESS IN THE CAW 00377000
LR R3,R1 REG 3 = SENSE ELEMENT ADDR FOR POSSIBLE FAST DISMI 00378000
LH R1,IOADDR REG.1 = DEVICE ADDRESS FOR SENSE SIO 00379000
IOSENSIO EQU * 00380000
SR R0,R0 CLEAR RETURN 00381000
SIO 0(R1) START THE SENSE OPERATION RUNNING 00382000
BC 8,IOSENTIO GO CHECK FOR FAST FINISH IF RUNNING 00383000
BC 3,IODISMIS FORGET IT IF NOT OPERATIONAL OR SUB-CHAN BUSY 00384000
CLI CSW+5,X'00' WERE THERE ANY ERRORS ON THE SENSE? 00385000
LA R0,12 ERROR POST CODE 00386000
BNE IODISMIS YEP - BAD NEWS 00387000
SR R0,R0 CLEAR OUT R0 00388000
CLI IOFAKE,X'00' HAVE WE ALREADY SET UP A FAKE INTERRUPT? 00389000
BNE IODISMIS YEP - BEST JUST TO QUIT NOW 00390000
MVC IOFAKE(R1),CSW+4 OTHERWISE ASSUME WE CLOBBERED AN INTRPT 00391000
B IOSENSIO AND TRY TO START THE SENSE AGAIN 00392000
IOSENTIO EQU * 00393000
TIO 0(R1) IS THE SENSE OPERATION DONE ALREADY? 00394000
BC 2,IOGO WAIT FOR INTERRUPT IF CHANNEL IS STILL BUSY 00395000
LA R0,12 ERROR POST CODE 00396000
BC 9,IODISMIS GIVE UP IF WEIRD THINGS ARE HAPPENING 00397000
TM CSW+4,X'0C' IS THE SENSE ALL DONE? 00398000
BM IOGO WAIT FOR DEVICE END INTERRUPT IF IT IS COMING 00399000
SR R0,R0 CLEAR RETURN 00400000
B IODISMIS OTHERWISE FREE, POST, AND RESTART SUB-CHANNEL 00401000
DROP R2 00402000
EJECT 00403000
IOFAKSET EQU * 00404000
CLI IOFAKE,X'00' HAS A FAKE INTERRUPT ALREADY BEEN SET UP? 00405000
MVI IOFAKE,X'00' CLEAR IT IN CASE IT HAS 00406000
BNE IOFINIS LOOPING - RETURN STATUS WITH NO FAKE INTERRUPT 00407000
MVC IOFAKE(1),CSW+4 MOVE STAT TO FAKE SAVE AREA @VM01107 00408010
CLI CSW+5,X'00' WERE ANY ERRORS ASSOCIATED WITH THE SIO? 00409000
BE IOSIO NOPE - GO BACK AND TRY IT AGAIN 00410000
MVI CSW+4,X'00' OTHERWISE CLEAR IRRELEVANT DEVICE STATUS 00411000
B IOFINIS AND LET THE I/O REQUEST TERMINATE WITH ERROR 00412000
SPACE 00413000
IOFAKEON EQU * 00414000
* BUSY STATUS BIT MUST BE ON HERE 00415000
XC CSW+1(7),CSW+1 CLEAR THE LOW ORDER SEVEN CSW BYTES 00416000
MVI CSW,X'0F' SET ILLEGAL BITS TO INDICATE FAKED INTERRUPT 00417000
MVC CSW+4(1),IOFAKE MOVE FAKED INTERRUPT DEVICE STAT TO CSW 00418000
NI CSW+4,X'EF' TURN OFF THE BUSY BIT 00419000
MVI IOFAKE,X'00' CLEAR THE INTERRUPT DEVICE STATUS SAVE AREA 00420000
SPACE 00421000
IOASYNCH EQU * 00422000
USING ASYNE,R2 GET ASYN ELEMENT ADDRESSABILITY 00423000
L R2,IOEXITQ REG 2 = ADDR OF START OF ASYNCH REQUEST QUEUE 00424000
IOASCAN EQU * 00425000
LTR R2,R2 ARE WE AT THE END OF THE QUEUE? 00426000
BZ IODISPCH IGNORE THE INTERRUPT IF NO REQUEST IS FOUND 00427000
CLC ASYNCODE(2),OLDIO+2 IS THIS A MATCHING DEVICE ADDR 00428000
BE IOASYNGO GO EXIT TO THE TASK'S ROUTINE IF SO 00429000
L R2,ASYNNEXT OTHERWISE REG.2 = ADDRESS OF NEXT ELEME 00430000
B IOASCAN AND LOOP AGAIN TO SNIFF AT THIS ONE 00431000
IOASYNGO EQU * 00432000
L R13,ASYNTASK PASS REQUESTOR'S TASK TAB ADDR TO HANDL 00433000
L R15,ASYNEXIT REG.15 = ADDRESS OF TASK'S REQUESTED EX 00434000
LA R14,IODISPCH SET RETURN REG FOR DIRECT RETURN TO DISPATC 00435000
BR R15 EXIT TO REQUESTED ASYNCHRONOUS ROUTINE ENTRY POINT 00436000
SPACE 00437000
IOFAKE DC H'0' FAKE STATUS SAVE AREA - PRESERVE ALIGNMENT 00438000
DROP R2 00439000
EJECT 00440000
DMTIOMRQ EQU * 00441000
SPACE 00442000
* I/O REQUEST ENTRY POINT FOR CALLS FROM TASKS 00443000
SPACE 00444000
FREEZE 00445000
SPACE 00446000
USING IOE,R2 GET I/O ELEMENT ADDRESSABILITY 00447000
L R12,NEWIO+4 REG.12 = A(DMTIOM) (BASE REG.) 00448000
LA R3,0(R1) REG.3 = ADDR OF CALLER'S I/O TABLE (TOP BYTE = 00449000
SR R1,R1 CLEAR REG.1 FOR SUP QUEUE GET REQUEST 00450000
L R15,QREQ REG.15 = SUP QUEUE MANAGER REQUEST ENTRY ADDR 00451000
BALR R14,R15 GET A FREE ELEMENT TO BUILD AN I/O ELEMENT 00452000
LTR R15,R15 DID IT WORK? 00453000
BNZ IOPUNT NO - QUIT FAST. 00454000
LR R2,R1 REG.2 = ADDR OF NEW I/O REQUEST ELEMENT 00455000
XC IONEXT(8),IONEXT CLEAR BOTH CHAINING FIELDS 00456000
XC SIOCOND(8),SIOCOND CLEAR FIXED RETURN INFO FIELDS 00457000
ST R3,IOTABLEA SET ADDRESS OF I/O TABLE IN QUEUE ELEMEN 00458000
MVC IOADDR(2),DEVCUU SET REQUESTED I/O DEVICE ADDR 00459000
L R1,ACTIVE GET THE ACTIVE TASK ELEMENT 00460000
MVC IOID(1),TASKID-TASKE(R1) SET REQUESTOR'S ID IN THE NEW E 00461000
CLI IOADDR,X'00' IS THE REQUEST FOR MULTIPLEXOR I/O? 00462000
BE IOMPXREQ YEP - GO DO MULTIPLEXOR REQUEST SETUP 00463000
MVC IOSBCHAN(1),IOADDR OTHERWISE CHANNEL ADDR = SUBCH 00464000
IOSETSEL EQU * 00465000
L R5,SELIOQ REG.5 = ADDRESS OF START OF SELECTOR QUEUE 00466000
LA R4,SELIOQ-(IONEXT-IOE) INITIALIZE LAST ELEMENT POINTER 00467000
SPACE 00468000
IORQSCAN EQU * 00469000
LTR R5,R5 IS THIS THE END OF THE QUEUE? 00470000
BZ IORQEND YES - ENQUEUE THE NEW ELEMENT AT THE END 00471000
CLC IOSBCHAN-IOE(1,R5),IOSBCHAN-IOE(R2) IS THIS THE SPOT TO 00472000
BNL IORQHIT YES - GO FIND OUT HOW TO DO IT 00473000
LR R4,R5 OTHERWISE SET THIS ELEMENT TO "LAST" ELEMENT 00474000
L R5,IONEXT-IOE(R5) AND CHAIN TO THE NEXT ELEMENT 00475000
B IORQSCAN CHECK THIS ELEMENT FOR HIT OR END 00476000
SPACE 00477000
IORQHIT EQU * 00478000
BE IORQBUSY SUB-CHANNEL IS BUSY IF EQUAL MATCH 00479000
ST R5,IONEXT OTHERWISE CHAIN NEW ELEMENT TO NEXT 00480000
IORQEND EQU * 00481000
ST R2,IONEXT-IOE(R4) CHAIN THE NEW ELEMENT TO THE LAST 00482000
B IOSTART AND GO DIRECTLY TO START THE I/O REQUEST 00483000
EJECT 00484000
IOMPXREQ EQU * 00485000
MVC IOSBCHAN(1),IOADDR+1 SUB-CHANNEL ADDR = UNIT ADDR 00486000
SPACE 00487000
SPACE 00498000
L R5,MPXIOQ OTHERWISE SET TO START MULTIPLEXOR QUEUE SCAN 00499000
LA R4,MPXIOQ-(IONEXT-IOE) INITIALIZE LAST ELEMENT POINTER 00500000
B IORQSCAN AND GO HUNT FOR A SPOT TO PUT THE NEW ELEMENT 00501000
EJECT 00505000
IORQBUSY EQU * 00506000
LR R6,R5 INITIALIZE NEXT ELEMENT POINTER FOR DMTQRQ SCAN 00507000
IORQDIVE EQU * 00508000
LR R5,R6 REG.5 = ADDRESS OF LAST SUBQUEUE ELEMENT 00509000
ICM R6,B'1111',IOSUBQ-IOE(R5) REG 6 = ADDRESS OF NEXT SUBQUE 00510000
BNZ IORQDIVE NOPE - KEEP TRUCKIN' ON DOWN THE LINE 00511000
ST R2,IOSUBQ-IOE(R5) YES - ENQUEUE THE NEW ELEMENT AT THE B 00512000
B IODISPCH AND GO BACK TO TASK EXECUTION 00513000
SPACE 00514000
IOPUNT EQU * 00515000
LA R1,IOSYNCH GET SYNCH LOCK ADDR 00516000
LA R0,16 SET RETURN CODE 00517000
L R15,POSTREQ GET SYSTEM POST ROUTINE 00518000
BALR R14,R15 GO POST IT 00519000
B IODISPCH AND CONTINUE 00520000
SPACE 00521000
LTORG 00522000
EJECT 00523000
COPY RSSEQU 00524000
EJECT 00525000
COPY SVECTORS 00526000
EJECT 00527000
COPY TAREA 00528000
EJECT 00529000
COPY TASKE 00530000
EJECT 00531000
COPY IOE 00532000
EJECT 00533000
COPY ASYNE 00534000
EJECT 00535000
COPY IOTABLE 00536000
END 00537000