The I/O Interrupt Routine is called from the low-level interrupt handler in the Nucleus module. The low-level handler saves the registers and interrupt PSW into the current TCB before transferring control to the IOIR.
000000 5 TXXIOIR CSECT , 000000 18CF 6 LR R12,R15 SET BASE 00000 7 USING TXXIOIR,R12 REGISTER 8 * 00000 9 USING @TCB,R4 10 * 000002 1F11 11 SLR R1,R1 ZERO R1 000004 BF13 401A 0001A 12 ICM R1,B'0011',TCBPSW+2 GET UNIT CUA FOR INTERRUPT 13 *
The address of the device generating the interrupt is obtained from the interrupt PSW.
000008 5850 0010 00010 14 L R5,16 CVT ADDRESS 00000C 5855 0008 00008 15 L R5,CVTUCB-@CVT(R5) POINT TO UCB LIST 00000 16 USING @UCB,R5 000010 18 UCB010 DS 0H 000010 D501 C11C 5004 0011C 00004 19 CLC =X'FFFF',UCBCUA END OF UCB LIST 000016 4780 C110 00110 20 BE IOHND060 UNKNOWN DEVICE 21 * 00001A BD13 5004 00004 22 CLM R1,B'0011',UCBCUA UCB FOR INTERRUPT 00001E 4780 C02A 0002A 23 BE UCB020 YES - CONTINUE 24 * 000022 5850 5000 00000 25 L R5,UCBNEXT POINT TO NEXT UCB 000026 47F0 C010 00010 26 B UCB010 LOOP BACK
The UCB table is searched to locate the UCB associated with the interrupt.
00002A 29 UCB020 DS 0H 00002A D207 501C 0040 0001C 00040 30 MVC UCBCSW,CSW-@LOWCORE SAVE CSW 000030 58A0 500C 0000C 31 L R10,UCBIOB POINT TO IORB 000034 12AA 32 LTR R10,10 IS THERE ONE 000036 4780 C0F6 000F6 33 BZ IOHND040 NO - BRANCH 34 * 00000 35 USING @IORB,R10 36 * 00003A 9180 A020 00020 37 TM IORBFLAG,IORBFSEN RESCHEDUE TO GET SENSE INFO 00003E 4710 C0AC 000AC 38 BO IOHND010 YES - SKIP NORMAL PROCESSING 39 * 000042 D207 A024 501C 00024 0001C 40 MVC IORBCSW,UCBCSW COPY CSW INTO IORB 000048 D500 C11E 5021 0011E 00021 41 CLC =X'80',UCBCSW+5 PCI ? 00004E 4710 C09E 0009E 42 BO PCI010 YES - BRANCH 43 * 000052 927F A021 00021 44 MVI IORBECBC,X'7F' PRIME I/O COMPLETION CODE 000056 D503 C118 5020 00118 00020 45 CLC =C'0C00',UCBCSW+4 DEV END + CHAN END 00005C 4780 C0AC 000AC 46 BE IOHND010 YES - GOOD COMPLETION 47 * 000060 9241 A021 00021 48 MVI IORBECBC,X'41' ERROR COMPLETION CODE 000064 9102 A024 00024 49 TM IORBCSW,X'02' UNIT CHECK ? 000068 47E0 C0AC 000AC 50 BNO IOHND010 NO - SKIP SENSE
When the UCB is located the CSW is saved into the UCB. A check is done to see if there is an outstanding I/O request for this device. If there is no outstanding request we branch to process an unsolicited interrupt. We then check to see is this is a reschedule of the IORB to get sense data. If it is a reschedule we can skip the normal processing.
Normal processing starts by copying the CSW into the IORB. A check is then done to see if the interrupt is a result of a Program Controlled Interrupt flag set in a CSW. If so we branch to call the PCI routine specified in the IORB. Next we check for good completion indicated by Device End + Channel End in the CSW. If not we set the ECB completion code to x’41’ and then examine the CSW to see if a Unit Check is indicated. If so we will issue a sense request to the device.
00006C 9680 A020 00020 52 OI IORBFLAG,IORBFSEN INDICATE SENSE IN PROGRESS 53 * 000070 4110 A022 00022 54 LA R1,IORBSEN0 SENSE AREA 000074 5010 A02C 0002C 55 ST R1,IORBWORK BUILD SENSE CCW 000078 9204 A02C 0002C 56 MVI IORBWORK,X'04' CMD=SENSE 00007C 4110 0002 00002 57 LA R1,2 LENGTH=2 000080 5010 A030 00030 58 ST R1,IORBWORK+4 000084 9220 A030 00030 59 MVI IORBWORK+4,X'20' SLI 60 * 000088 4110 A02C 0002C 61 LA R1,IORBWORK POINT TO SENSE CCW 00008C 5010 0048 00048 62 ST R1,CAW-@LOWCORE SAVE INTO CAW 000090 1F11 63 SLR R1,R1 CLEAR R1 000092 BF13 5004 00004 64 ICM R1,B'0011',UCBCUA GET UNIT ADDRESS 000096 9C00 1000 00000 65 SIO 0(R1) 00009A 47F0 C106 00106 66 B IOHND050 AND EXIT
We begin by setting the bit in the IORB to indicate sense in progress. We then build a Sense CCW in the work area and then issue a SIO to the device to obtain the first two bytes of sense data.
00009E 69 PCI010 DS 0H 00009E 4110 A000 00000 70 LA R1,@IORB POINT TO IORB 0000A2 58F0 A018 00018 71 L R15,IORBPCI GET PCI ROUTINE ADDR 0000A6 05EF 72 BALR R14,R15 CALL IT 0000A8 47F0 C106 00106 73 B IOHND050 AND EXIT
Here we handle a PCI interrupt by calling the PCI routine specified in the IORB.
0000AC 76 IOHND010 DS 0H 0000AC 4110 A000 00000 77 LA R1,@IORB POINT TO IORB 0000B0 58F0 A014 00014 78 L R15,IORBDIE DIE ROUTINE ADDRESS 0000B4 05EF 79 BALR R14,R15 CALL DIE 80 * 0000B6 18BA 81 LR R11,R10 SAVE IORB ADDRESS 82 * 0000B8 83 IOHND020 DS 0H 0000B8 58A0 A000 00000 84 L R10,IORBNEXT POINT TO NEXT IORB ON CHAIN 0000BC 50A0 500C 0000C 85 ST R10,UCBIOB UPDATE IOB CHAIN OFF UCB 86 * 0000C0 12AA 87 LTR R10,R10 ANOTHER IORB TO SCHEDULE 0000C2 4780 C0D8 000D8 88 BZ IOHND030 NO - BRANCH 89 * 0000C6 5810 A00C 0000C 90 L R1,IORBCCW GET CCW 0000CA 5010 0048 00048 91 ST R1,CAW-@LOWCORE SAVE INTO CAW 0000CE 1F11 92 SLR R1,R1 ZERO R1 0000D0 BF13 5004 00004 93 ICM R1,B'0011',UCBCUA GET DEVICE ADDRESS 0000D4 9C00 1000 00000 94 SIO 0(R1)
Now we are ready to call the DIE routine specified in the IORB. We can then remove the IORB from the UCB queue and check to see if there is another IORB to process. If so we issue the SIO for the request.
0000D8 96 IOHND030 DS 0H 0000D8 18AB 97 LR R10,R11 RESTORE IORB ADDRESS 0000DA 5840 A010 00010 98 L R4,IORBTCB GET TCB TO DISPATCH 0000DE 5810 0010 00010 99 L R1,16 CVT 0000E2 5810 1004 00004 100 L R1,CVTTASKQ-@CVT(,R1) PONIT TO TCB QUEUE = A(WAIT TCB) 0000E6 5820 1000 00000 101 L R2,TCBNEXT-@TCB(,R1) NEXT TCB 0000EA 5020 4000 00000 102 ST R2,0(,R4) CHAIN ON 0000EE 5040 1000 00000 103 ST R4,0(,R1) NEW TCB 0000F2 47F0 C106 00106 104 B IOHND050 AND EXIT
Final processing consists of adding the TCB specified in the IORB to the Task Queue. We chain it on immediately after the Wait Task TCB.
0000F6 107 IOHND040 DS 0H 0000F6 58F0 5010 00010 108 L R15,UCBINTR UCB INTERRUPT ADDRESS 0000FA 12FF 109 LTR R15,R15 BRANCH 0000FC 4780 C106 00106 110 BZ IOHND050 IF NONE 111 * 000100 4110 5000 00000 112 LA R1,@UCB POINT TO UCB 000104 05EF 113 BALR R14,R15 CALL INTERRUPT ROUTINE
Here we handle an unsolicited interrupt. If an interrupt routine is specified in the UCB we branch to it passing the address of the UCB in Register 1.
000106 116 IOHND050 DS 0H 000106 58F0 0014 00014 117 L R15,20 MVT 00010A 58F0 F004 00004 118 L R15,MVTDISP-@MVT(,R15) DISPATCHER 00010E 07FF 119 BR R15 120 * 000110 122 IOHND060 DS 0H 000110 47F0 C106 00106 123 B IOHND050
Eventually we exit back to the Dispatcher.
[Next – ]