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