.TITLE MB .IDENT /14NOV9/ ;+ ; - M B ;****NAME: MB.... ; FILE: MB11D.MAC ; TKB: MB11D.BLD ; ;****PURPOSE: RSX11D HANDLER TO TRANSFER ARBITRARILY LONG BLOCKS OF ; DATA BETWEEN TASKS ; ;****RESTRICTIONS: ; 1. APR4 MUST MAP THE NODE POOL ONLY AND NOT ANY OF ; THE SCOM ROUTINES AND TABLES SINCE IT IS USED TO MAP ; TO ONE OF THE REQUESTING TASK'S BUFFERS DURING THE ACTUAL ; TRANSFER OF DATA. AN ERROR MESSAGE WILL BE PUT OUT AT LOAD ; TIME IF THE EXECUTIVE MAPPING IS INCOMPATIBLE WITH THIS ; REQUIREMENT. ; ; SYSTEM: RSX-11D V6.2 ; LANGUAGE: MACRO ; AUTHOR: T.KOZLOWSKI, M. OOTHOUDT ; GROUP MP-1, M.S. 828 ; LOS ALAMOS SCIENTIFIC LABORATORY ; LOS ALAMOS, N.M. 87545 ; ; DATE: 26-MAR-79 ; REVISIONS: ; 14-JUN-79 (MAO) TRANSFER BY BYTE, NOT BY WORD ; 18-JUN-79 (MAO) CHANGE BHIS TO BLOS IN XFER LOOP TO FIX ERROR FOR ; >8064. BYTE TRANSFERS. ; 14-NOV-79 (MAO) ADD RESULTS OF TIMING TESTS ; ;****CALLING SEQUENCE: ; ; QIO$ FNC,LUN,[EF],[PRI],[IOST],[AST], ; ; INPUT: ; ; FNC= IO.RVB - READ VIRTUAL BLOCK ; IO.WVB - WRITE VIRTUAL BLOCK ; IO.KIL - KILL ALL REQUESTS (PARAMETERS <...> IGNORED FOR THIS QIO) ; IO.RDN - I/O RUNDOWN (ONLY ALLOWED FROM EXECUTIVE) ; IO.UNL - UNLOAD HANDLER (ONLY ALLOWED FROM EXECUTIVE) ; LUN= LOGICAL UNIT # TO USE FOR I/O ; EF= EVENT FLAG TO BE SET WHEN I/O COMPLETED ; PRI= PRIORITY OF QIO ; IOST= ADDRESS OF I/O STATUS BLOCK ; AST= ADDRESS OF AST SERVICE ROUTINE TO EXECUTE AT END OF TRANSFER ; BADR= ADDRESS OF USER BUFFER CONTAINING OR TO RECEIVE DATA ; SZ= NUMBER OF BYTES TO TRANSFER (.LE.64K; ACTUAL NUMBER TRANSFERED ; WILL BE MINIMUM OF SZ AND SZ FROM REFERENCED TASK) ; TNAM1=FIRST 3 CHARACTERS OF NAME OF REFERENCED TASK IN RAD50 ; TNAM2=LAST 3 CHARACTERS OF NAME OF REFERENCED TASK IN RAD50 ; PARM= LOW BYTE: TERMINAL NUMBER+1 OF REFERENCED TASK OR 0 IF TASK ; WITH GIVEN NAME FROM ANY TERMINAL IS OK. ; HIGH BYTE: BIT 0--SET IF MB IS TO REJECT QIO IF REFERENCED TASK ; IS NOT INSTALLED. ; BIT 1--SET IF MB IS TO REJECT QIO IF COMPLIMENTARY ; I/O REQUEST HAS NOT BEEN RECEIVED BY MB FROM ; REFERENCED TASK. ; ; OUTPUT: ERROR/SUCCESS CODES (RETURNED IN I/O STATUS BLOCK) ; ; IE.IFC - INVALID FUNCTION CODE (FNC NOT ONE OF ABOVE OR ; IO.RDN OR IO.UNL FROM USER LEVEL CODE) ; IE.DNR - DEVICE NOT READY (COMPLIMENTARY I/O REQ IS NOT IN ; HANDLER QUEUE; SET ONLY IF BIT 1 OF 'PARM' HI BYTE ; IN QIO PARAMETER LIST WAS SET) ; IE.BAD - BAD PARAMETER (INVALID TASK NAME OR IF LOW BYTE ; OF 'PARM' NONZERO AND REFERENCED TT NOT IN SYSTEM) ; IE.NST - SPECIFIED TASK NOT INSTALLED (SET ONLY IF BIT 0 OF LOW ; BYTE OF 'PARM' HAS BEEN SET IN QIO) ; IE.SPC - ILLEGAL USER BUFFER LIMITS (BADR OR SZ BAD) ; IE.ABO - REQUEST TERMINATED (HANDLER UNLOADED BEFORE TRANSFER ; COMPLETED) ; IS.PND - OPERATION PENDING (MB WAITING FOR MATCHING REQUEST) ; IS.SUC - TRANSFER SUCCESSFUL ; ; ; ; RESOURCES: ; LIBRARIES: NONE ; OTHER SUBR: ; SCOM ROUTINES: ..DISP, ..DNRC, ..DQRE, ..DQRN, ..DSUT, ..FLSH, ; ..FSTD, ..IODN, ..SPD3, ..SPD4, ..VXFR, ..NDEL ; EVENT FLAGS: LOCAL FLAGS 1 AND 2 AND 4 ; SYSTEM DIR: NONE ; LENGTH/PAR: 2526 OCTAL BYTES ; ;****NOTES: ; 1. THIS HANDLER TRANSFERS DATA BETWEEN BUFFERS IN TWO TASKS. ; THE ALGORITHM USED IS THE FOLLWING: TASK A ISSUES A QIO ; REFERENCING TASK B (IN PARAMETER LIST) TO READ A BLOCK OF ; DATA FROM (OR WRITE TO) TASK B. IF TASK B HAS ISSUED (OR ; WHENEVER IT DOES ISSUE) A QIO REFERENCING TASK A TO ; DO THE COMPLIMENTARY TRANSFER, IE., A WRITE TO (READ FROM) ; TASK A, THE HANDLER RECOGNIZES THE PAIR OF QIO'S AND ; CARRIES OUT THE DATA TRANSFER. ; ; 2. I/O COMPLETION FOR THE ISSUED QIO DOES NOT OCCUR UNTIL ; THE TRANSFER HAS TAKEN PLACE. ; ; 3. THE MB HANDLER REMOVES I/O REQUESTS FROM ITS I/O QUE ; AS THEY ARE RECEIVED AND STORES THEM IN ONE OF ; ITS OWN TWO INTERNAL QUEUES (A READ AND A WRITE QUEUE) ; UNTIL THE TRANSFER HAS TAKEN PLACE, AFTER WHICH IT RETURNS ; THE PAIR OF NODES TO THE POOL AND ISSUES RESPECTIVE ; I/O COMPLETIONS TO THE TASKS. ; ; 4. FUNCTION IO.KILL KILLS ALL OUTSTANDING QIO'S FROM REQUESTING ; TASK TO MB, NOT JUST MOST RECENT QIO. ; ; 5. TIMING TESTS FOR MB. THE TESTS WERE DONE ON THE ; PROGRAM DEVELOPMENT PDP-11/34 UNDER RSX-11D V6.2 (MAO, 14-NOV-79). ; TWO TASKS WERE USED. TIMTGT WAS THE TARGET OF THE TRANSFER AND SIMPLY ; REQUEUED THE QIO WHEN IT GOT A MESSAGE. TIMSRC DID A WRITE TO ; TIMTGT WITH TI INPUT OF THE NUMBER OF WORDS TO TRANSFER AND ; THE NUMBER OF TRANSFERS TO AVERAGE THE TRANSFER TIME OVER. ; THESE ROUTINES ARE ON DP1:[22,206]. THE NUMBER OF TRANSFERS TO ; AVERAGE WAS VARIED TO USE APPROXIMATELY THE SAME AMOUNT OF WALL CLOCK ; TIME FOR EACH BLOCK SIZE TESTED (ACTUALLY THIS DOESN'T MAKE MUCH ; DIFFERENCE EXCEPT FOR SMALL BLOCKS WHERE AT LEAST 100 TRANSFERS ; MUST BE AVERAGED OVER TO GET CONSISTENT RESULTS). THE AVERAGING ; WAS DONE OVER 100 TRIES FOR 32000. BYTE BLOCKS AND 500 TRIES FOR ; 500. BYTE BLOCKS. TESTS WERE DONE FOR 500., 1000., 2000., 4000., ; 8000.,...,32000. BLOCKS. THE RESULTS WERE ABSOLUTELY LINEAR, GIVING ; ; TIME = 16.7 MILLISECONDS + 6.9 MICROSECONDS/BYTE * N ; ; WHERE N = NUMBER OF BYTES TRANSFERRED. NOTE THE CONSTANT IS EXACTLY ; ONE TICK OF THE SYSTEM CLOCK AND MAY REFLECT SOMETHING OTHER THAN ; TRANSFER TIME. ; ;- .PAGE .SBTTL INITIALIZATION .MCALL CALL,DIR$,WTLO$S,EXIT$S,QIOW$S ; ; CHECK THAT APR4 MAPS THE NODE POOL ONLY ; INIT: CMP .PUDBA,#120000 ;PUD LSTHD + 1 UNDER APR4? BHI INIT1 ;PUT OUT FAILURE MESSAGE, WAIT QIOW$S #IO.WVB,#1,#4,,,,<#MSGB,#,#40> JMP EXIT ;EXIT: APR4 IS USED TO MAP SCOM ;TABLES/ROUTINES SO WE CANNOT ;USE IT AS NEEDED. MSGB: .ASCII /MB.... INITIALIZATION FAILURE. BAD APR4 MAPPING/ MSGE: .EVEN ;MAKE BOUNDARY EVEN ; ; DETERMINE MAX TT NUMBER IN SYSTEM (FOR LATER USE) ; INIT1: MOV .PUDBA,R5 ;GET START OF PUD TABLE 20$: CMP .PUDEA,R5 ;LAST ENTRY? BEQ 40$ ;BRANCH IF IT IS CMP TT,U.DN(R5) ;TT ENTRY? BNE 30$ ;BRANCH IF IT ISN'T CMPB MXTTP1,U.UN(R5) ;LARGER UNIT NO.? BHI 30$ ;BRANCH IF NOT MOVB U.UN(R5),MXTTP1 ;SAVE NEW MAX UNIT NO. 30$: ADD #U.SZ,R5 ;POINT R5 AT NEXT PUD ENTRY BR 20$ ;TRY AGAIN 40$: INCB MXTTP1 ;FINISHED, STORE MAX TT+1 ; ; DECLARE HANDLER RESIDENT ; MOV #UIT,R0 ;POINT R0 TO UIT MOV MB,R2 ;PUT DEVICE NAME IN R2 MOV #UF.RH,R3 ;PUT PUD FLAG IN R3 CALL ..DSUT ;DECLARE RESIDENT BCC 50$ JMP EXIT ;EXIT IF ERROR 50$: MOV PC,SP ;SET STACK TO OVERLAP INIT CODE .PAGE .SBTTL IDLE LOOP AND DISPATCHER IDLE: TST UNLFLG ;UNLOAD FLAG SET? BEQ 10$ JMP DOUNL ;YES, UNLOAD ; ; WAIT AND CHECK FOR EVENT FLAGS 1 OR 2 ; 10$: WTLO$S 0,#3 ;WAIT FOR EVENT FLAGS 1 OR 2 MOV #UIT,R0 ;PUT UIT ADDRESS IN R0 MOV .CRTSK,R3 ;GET HANDLER ATL ADDRESS MOV A.EF(R3),R5 ;PUT EVENT FLAG WORD IN R5 BIT #2,R5 ;EVENT FLAG 2 SET? BEQ 20$ ;NO, CHECK 1 CALL ..DQRE ;ATTEMPT TO DEQUE EXPR REQ BCC VALID ;NODE FOUND? 20$: BIT #1,R5 ;NO, IS EVENT FLAG 1 SET? BEQ IDLE ;IF NOT GO BACK TO IDLE CALL ..DQRN ;ATTEMPT TO DEQUE NORMAL REQ BCS IDLE ;NODE FOUND? IF NOT, SLEEP. ; ; VALIDATE REQUEST ; ; ON ENTRY: ; R0 CONTAINS PTR TO UIT ; R1 CONTAINS PTR TO I/O REQUEST NODE (RNA) ; R2 CONTAINS PTR TO PUD PTR IN UIT ; VALID: MOV #IE.IFC,R3 ;ASSUME ERROR CMPB MAXFNC,R.FC+1(R1) ;CHECK FUNCTION CODE (HI BYTE) BLO 20$ ; ; NOTE AT THIS POINT NORMAL HANDLER WOULD CALL ..VACC. WE HOWEVER ; DO NOT HAVE ANY ACCESS RIGHTS TO CHECK. ; ; ; DISPATCH REQUEST TO PROCESSOR ; (FUNCTION PROCESSORS ALL JMP TO IDLE WHEN DONE) ; JMP ..DISP ; ; JUMP TO ERROR ROUTINE ; 20$: JMP ERROR .PAGE .SBTTL NORMAL FUNCTION PROCESSORS ;;;;;;;;;; ; PROCESSORS ;;;;;;;;;; ; ; READ PROCESSOR (RVB) ; READ: CLR RWFLAG ;SET R/W FLAG FOR READ MOV #WQU,SCANHD ;SET UP WRITE QUE AS SCAN QUE BR RWPROC ;PROCESS REQUEST ; ; WRITE PROCESSOR (WVB) ; WRITE: MOV #1,RWFLAG ;SET R/W FLAG FOR WRITE MOV #RQU,SCANHD ;SET UP READ QUE AS SCAN QUE BR RWPROC ;PROCESS REQUEST ; ; ILLEGAL FUNCTION PROCESSOR ; ILLGL: MOV #IE.IFC,R3 ;SET ILLEGAL FNC CODE JMP ERROR ; ; ; ;;;;;;;;;; ; READ/WRITE REQUEST PROCESSING ;;;;;;;;;; ; ; REGISTERS ON ENTRY: ; R0 PTR TO UIT ; R1 RNA ; R2 PTR TO PUD PTR IN UIT ; RWPROC: CALL CHECK ;CHECK I/O REQ PARAMETERS BCC 5$ ;CONTINUE IF NO ERROR JMP ERROR 5$: CALL SCANQ ;SCAN COMPLIMENTARY QUE TST MATCH ;I/O REQ MATCH? BEQ 10$ ;NO MATCH, BRANCH JMP XFER ;MATCH, CARRY OUT DATA TRANSFER 10$: BITB CHKMAT,FLGS ;FATAL ERROR IF NO MATCH? BEQ 20$ ;IF ZERO, NOT FATAL ERROR MOV #IE.DNR,R3 ;SET DEVICE NOT READY IF NO MATCH JMP ERROR 20$: JMP SAVNOD ;SAVE NODE IN RQU OR WQU ; ; ; ;;;;;;;;;; ; SUBROUTINE CHECK - CHECK I/O REQUEST PARAMETERS ;;;;;;;;;; CHECK: ; ; CHECK REFERENCED TASK NAME ; TST R.PB+4(R1) ;1ST PART OF TASK NAME NON-ZERO? BNE 10$ ;NONZERO, TASK NAME OK MOV #IE.BAD,R3 ;SET BAD PARAM. ERROR BR ERR ;GO PROCESS ERROR ; ; CHECK REFERENCED TASK TT NO. ; 10$: MOVB R.PB+10(R1),TTNO ;SAVE REFER'D TASK TTNO+1 BEQ 30$ ;DON'T CHECK IF = 0 CMPB MXTTP1,TTNO ;.LE. MAX TT NO. FOR SYSTEM? BHIS 30$ ;YES, CONTINUE 20$: MOV #IE.BAD,R3 ;NO,SET BAD PARAM. ERROR BR ERR ;GO PROCESS ERROR ; ;OK, FOUND REFERENCED TT ; ; CHECK BUFFER MEMORY LIMITS ; 30$: MOV R.PB(R1),R2 ;SET UP TO CHECK BUFF MEM. LIMITS MOV R.PB+2(R1),R3 MOV RWFLAG,R5 CALL ..VXFR ;CHECK LIMITS BCC 40$ ;MEM. LIMITS OK, CONTINUE 35$: MOV #IE.SPC,R3 ;SET ILLEG. USER BUFFER ERROR BR ERR ;GO PROCESS ERROR 40$: ASH #-4,R4 ;RE-ALIGN HI-BITS TO BIT 0 MOV R4,R.WA+2(R1) ;SAVE PHYSICAL ADDRESS IN MOV R5,R.WA+4(R1) ;I/O REQ NODE WORK AREA ; ; CHECK THAT REFERENCED TASK IS INSTALLED, IF DESIRED ; MOV R1,RNA ;SAVE I/O REQ PTR MOVB R.PB+11(R1),FLGS ;SAVE FLAG PARAMETER BITB CHKINS,FLGS ;CHECK IF REFER'D TASK INSTALLED? BEQ OK ;NO, DON'T CHECK ADD #R.PB+4,R1 ;POINT R1 AT REFERENCED TASK NAME CALL ..FSTD ;SEARCH STD FOR REFER'D TASK MOV RNA,R1 ;RESTORE I/O REQ PTR TST R2 ;NOT THERE IF (R2)=0 BNE OK MOV #IE.NST,R3 ;NO, SET SPEC. TASK NOT INSTAL. BR ERR ;GO PROCESS ERROR ERR: SCC ;SET ERROR CONDITION CODE BR RETURN OK: CCC ;SET NO-ERROR CONDITION CODE RETURN: RTS PC ;RETURN TO MAIN PROCESSOR CODE ; ; ; ;;;;;;;;;; ; SUBROUTINE SCANQ TO SCAN READ OR WRITE QUE FOR COMPLIMENTARY I/O REQ ;;;;;;;;;; ; ; REGISTERS USED: ; R0=PTR TO UIT ; R1=RNA ; R2,R3=REQUESTOR TASK NAME ; R4=QUE POINTER ; R5=SCRATCH ; SCANQ: ; ; SET UP FOR SCAN ; MOV R.TD(R1),R3 ;PT. R3 AT STD ENTRY OF REQUESTOR MOV (R3)+,R2 ;PUT REQUESTOR NAME IN R2,R3 MOV (R3),R3 ;GET TT NO. OF REQUESTOR MOV R.AT(R1),R5 ;POINT R5 AT ATL ENTRY MOV A.TI(R5),R5 ;POINT R5 AT PUD ENTRY OF TT NO. MOVB U.UN(R5),R5 ;PUT TT NO. IN R5 INCB R5 ;ADD ONE MOVB R5,TTNOA ;AND SAVE MOV SCANHD,R4 ;SET UP R4 AS QUE PTR CLR MATCH ;INITIALIZE MATCH FLAG TO ZERO ; ; SCAN LOOP ; ;FIND A NODE IN SCANQ FROM THE ;REFERENCED TASK & TT TO MATCH ;THE NEW NODE WE ARE PROCESSING 10$: MOV (R4),R4 ;POINT R4 AT NEXT NODE CMP R4,SCANHD ;CHECK IF END OF QUE BEQ 20$ ;YES, EXIT LOOP ;1ST CHECK IF ENTRY IN SCANQ ;POINTS TO SENDER OF RNA NODE CMP R2,R.PB+4(R4) ;1ST HALF TASK NAME MATCH? BNE 10$ ;IF NO, GET NEXT NODE CMP R3,R.PB+6(R4) ;2ND HALF TASK NAME MATCH? BNE 10$ ;IF NOT, GET NEXT NODE TSTB R.PB+10(R4) ;MATCH. TEST TT NO.? BEQ 30$ ;IF ZERO, DON'T TEST CMPB TTNOA,R.PB+10(R4) ;TT NO.'S MATCH? BNE 10$ ;IF NOT, TRY NEXT NODE ; ;NOW WE KNOW SCANQ ENTRY POINTS ;TO SENDER OF RNA NODE. DOES RNA ;POINT TO SCANQ NODE? 30$: MOV R.TD(R4),R5 ;PT. R5 AT STD ENTRY OF Q ENTRY CMP (R5),R.PB+4(R1) ;DO TASK NAMES MATCH (1ST HALF) BNE 10$ ;IF NOT GET ANOTHER Q ENTRY CMP 2(R5),R.PB+6(R1) ;2ND HALF OF NAMES MATCH? BNE 10$ ;NO, TRY ANOTHER NODE TSTB TTNO ;CHECK TT NO.'S? BEQ 40$ ;IF 0, DON'T MOV R.AT(R4),R5 ;PT. R5 AT ATL ENTRY MOV A.TI(R5),R5 ;PT. R5 AT TT PUD ENTRY MOVB U.UN(R5),R5 ;PUT TT NO. IN R5 INCB R5 ;ADD ONE CMPB R5,TTNO ;TT NO.'S MATCH? BNE 10$ ;IF NOT, GET ANOTHER Q ENTRY ; ; COME HERE ON MATCH ; 40$: MOV R4,MATCH ;SAVE ADDRESS OF MATCHING NODE ; ; RETURN ; 20$: RTS PC ; ; ; ;;;;;;;;;; ; XFER - CODE TO PERFORM INTER-TASK DATA TRANSFER ;;;;;;;;;; XFER: ; ; SET UP FOR TRANSFER ; ; REGISTERS ON ENTRY: ; R0 = UIT PTR ; R1 = CURRENT REQ NODE ADDRESS ; R4 = COMPLIMETARY REQ NODE ADDRESS ; ; R1-R5 ARE DESTROYED BY THE 'XFER' CODE ; MOV R.PB+2(R4),R5 ;GET COMPLIMENTARY XFER LENGTH MOV R.WA+2(R4),PADDR2 ;SAVE PHYS.ADDR FROM COMPL.NODE MOV R.WA+4(R4),PADDR2+2 MOV R.PB+2(R1),R4 ;GET PRESENT REQ NODE XFER LENGTH MOV R.WA+2(R1),PADDR1 ;SAVE PHYS.ADDR FROM REQ NODE MOV R.WA+4(R1),PADDR1+2 CMP R5,R4 ;TRANSFER MIN NO. BYTES BHIS 9$ ;(R4) = TOTAL NO. BYTES TO XFER MOV R5,R4 9$: MOV R4,BCNT ;SAVE XFER BYTE COUNT FOR LATER CLRB LOCFLG ;CLEAR FLAG FOR 1ST TIME THROUGH ; ; TRANSFER LOOP ; ; 4032. WORDS ARE TRANSFERRED AT ; A TIME. 4064. WOULD SEEM MORE ; PROPER, BUT THE SCOM TRANSFER ; ROUTINES FOR SOME UNKNOWN REASON ; USE 4032. SO WE'LL USE IT TO BE ; SAFE. (8064. BYTES) 10$: MOV R4,R5 ;ASSUME TRANSFER .LT. 8064. BYTES CMP R5,#8064. ;XFER ONLY 8064. BYTES AT A TIME BLOS 20$ MOV #8064.,R5 ;.GT. 8064., SET UP FOR 1 BLOCK 20$: ; SET UP APR3 TO MAP REQ NODE BUFFER MOV PADDR1,R0 ;PUT HI BITS OF PHYS.ADDR. IN R0 MOV PADDR1+2,R1 ;PUT LO BITS OF PHYS.ADDR. IN R1 DIV #100,R0 ;DIVIDE BY 100 (64.) ADD #60000,R1 ;(R1)=HANDLER VIR.ADDR. OF BUFF. MOV #77406,-(SP) ;SET UP TO MAP MOV R0,-(SP) CALL ..SPD3 ;MAP TO BUFFER ; SET UP APR4 TO MAP COMPL. NODE BUFFER MOV PADDR2,R2 ;PUT HI BITS OF PHYS.ADDR. IN R2 MOV PADDR2+2,R3 ;PUT LO BITS OF PHYS.ADDR. IN R3 DIV #100,R2 ;DIVIDE BY 100 (64.) ADD #100000,R3 ;(R3) = HANDLER VIR.ADDR. OF BUFF. MOV #77406,-(SP) ;SET UP TO MAP MOV R2,-(SP) CALL ..SPD4 ;MAP TO BUFFER ; ACTUAL TRANSFER TST RWFLAG ;CHECK IF XFER DIRECTION CORRECT BNE 30$ ;IF NON-ZERO, YES XOR R1,R3 ;NO, SWAP REGISTERS XOR R3,R1 XOR R1,R3 30$: MOVB (R1)+,(R3)+ ;MOVE DATA SOB R5,30$ ; SET UP FOR NEXT LOOP, IF THERE IS ONE TSTB LOCFLG ;1ST TIME THRU,DON'T POP STACK ;SINCE WE WILL WANT TO RESTORE ;THESE VALUES WHEN ALL DONE. BEQ 31$ TST (SP)+ ;DISCARD PAR'S AND PDR'S AND PDR'S ;FOR INTERMEDIATE BLOCKS XFERED TST (SP)+ TST (SP)+ TST (SP)+ 31$: INCB LOCFLG ;INCREMENT 1ST TIME THRU FLAG SUB #8064.,R4 ;ANY MORE BYTES TO TRANSFER? ;BLOS IS THE RIGHT TEST!!!! MAO BLOS ENDREQ ;IF NOT TERMINATE ADD #8064.,PADDR1+2 ;UPDATE REQ NODE BUFFER PHYS.ADD. BCC 40$ INC PADDR1 40$: ADD #8064.,PADDR2+2 ;UPDATE COMPL NODE BUFFER PHY.AD. BCC 50$ INC PADDR2 50$: JMP 10$ ;BACK TO BEGINNING OF LOOP ; ; COMPLETE PROCESSING FOR READ/WRITE I/O REQUEST ; ENDREQ: CALL ..SPD4 ;RE-MAP APR4 TO OLD VALUES TST (SP)+ ;RESTORE STACK TST (SP)+ TST (SP)+ ;THROW AWAY APR3 VALUES TST (SP)+ ; SINCE NOT USED ; SET UP AND DO IODONE FOR BOTH NODES MOV RNA,R1 ;POINT R1 TO REQ NODE CLR R2 ;ZERO ADJUSTMENT TO DECREMENT MOV #IS.SUC,R3 ;SET SUCCESS STATUS MOV BCNT,R4 ;PUT BYTE COUNT IN R4 CALL ..IODN MOV MATCH,R4 ;POINT R4 AT COMPLIMENTARY NODE CALL ..NDEL ;DELETE NODE FROM INTERNAL DEQUE CLR NRNA ;ZERO RNA IN UIT FOR REQ NODE MOV MATCH,R1 ;POINT R1 TO COMPL. NODE CLR R2 ;ZERO ADJUSTMENT TO DECREMENT MOV #IS.SUC,R3 ;SET SUCCESS STATUS MOV BCNT,R4 ;PUT BYTE COUNT IN R4 CALL ..IODN JMP IDLE ;GO TO SLEEP ; ; ; ;;;;;;;;;; ; SAVNOD - CODE TO SAVE A RD/WR I/O REQ NODE IN HANDLER INTERNAL QUEUE ;;;;;;;;;; ; ; REGISTERS ON ENTRANCE ; R0=PTR TO UIT ; R1=RNA ; R2=PTR TO PUD PTR IN UIT ; SAVNOD: ; ; INSERT NODE IN HANDLER INTERNAL Q ; MOV #RQU,R3 ;ASSUME I/O REQ IS READ TST RWFLAG ;DIRECTION OF XFER? BEQ 10$ ;ZERO = READ MOV #WQU,R3 ;WRITE, SAVE LISTHEAD IN R3 ; UPDATE PRESENT I/O REQ NODE 10$: MOV R3,(R1) ;FORW. PTR. POINTS TO LISTHEAD MOV 2(R3),2(R1) ;BACKW. PTR. POINTS TO LAST NODE ; UPDATE LAST LAST NODE IN QUE MOV R1,@2(R3) ;FORW. PTR. PTS TO PRESENT NODE ; UPDATE LISTHEAD MOV R1,2(R3) ;BACKW. PTR. PTS TO PRESENT NODE ; SET PRIORITY TO 50 MOVB #50.,R.PR(R1) ; ZERO RNA IN UIT SO ANOTHER I/O REQ NODE MAY BE PROCESSED CLR NRNA ; IDLE JMP IDLE .PAGE .SBTTL SPECIAL FUNCTION PROCESSORS ;;;;;;;;;; ; SPECIAL FUNCTION DISPATCHER ;;;;;;;;;; SPECL: CMP #IO.KIL,R.FC(R1) ;KILL ALL REQUESTS? BEQ KILL ;YES, GO TO KILL CODE MOV #IE.IFC,R3 ;ASSUME ERROR FOR FOLLOWING TST R.AT(R1) ;EXEC REQ? ,MUST BE FOR REMAINING BEQ 20$ ; FUNCTIONS (IO.RDN OR IO.UNL) JMP ERROR ;ILLEGAL FUNCTION 20$: CMP #IO.RDN,R.FC(R1) ;O.K., RUNDOWN? BEQ RUNDWN ;YES, GO TO RUNDOWN CODE CMP #IO.UNL,R.FC(R1) ;UNLOAD? BEQ 40$ ;YES JMP ERROR ;NO,REPORT ERROR ;(ERROR # ALREADY IN R3) 40$: INC UNLFLG ;SET UNLOAD FLAG CALL ..IODN ;DO COMPLETION ON UNLOAD NODE CLR ERNA ;ZERO EXPRESS RNA IN UIT JMP IDLE ;BACK TO IDLE ;;;;;;;;;; ; KILL ALL REQUESTS PROCESSOR ;;;;;;;;;; KILL: MOV R.AT(R1),R.PB(R1) ;PUT ATL ENTRY ADDR IN PARAM.1 MOV R.TD(R1),R.PB+2(R1) ;PUT STD ENTRY ADDR IN PARAM.2 MOV R.PD(R1),R.PB+4(R1) ;PUT PUD PTR IN PARAM.3 ;FALL INTO RUNDOWN ;;;;;;;;;; ; I/O RUNDOWN PROCESSOR ;;;;;;;;;; RUNDWN: ; ; FLUSH I/O REQ NODES FOR TASK IN HANDLER QUEUE ; CALL ..FLSH ; ; FLUSH I/O REQ NODES FOR TASK IN INTERNAL READ REQ QUEUE ; MOV .CRTSK,R3 ;PUT HANDLER ATL ADDR IN R3 MOV #77406,-(SP) ;MAP APR3 TO TASK HEADER MOV A.HA(R3),-(SP) CALL ..SPD3 MOV #60000+H.IOQ,R4 ;POINT R4 TO HANDLER IOQ LISTHEAD MOV (R4),IOQSAV ;SAVE HANDLER I/O Q LISTHEAD MOV 2(R4),IOQSAV+2 MOV RQU,(R4) ;PUT READ Q LISTHEAD IN HANDLER MOV RQU+2,2(R4) ;I/O Q LISTHEAD MOV (R4),R2 ;POINT R2 AT FIRST QUE ENTRY MOV 2(R4),TEMP ;SAVE LAST QUE ENTRY ADDR IN TEMP MOV #60000+H.IOQ,2(R2) ;POINT BACK PTR AT NEW LISTHEAD MOV TEMP,R2 ;POINT R2 AT LAST QUE ENTRY MOV #60000+H.IOQ,(R2) ;POINT FORW. PTR AT NEW LISTHEAD CALL ..FLSH ;FLUSH NODES ;UPDATE READ Q LISTHEAD (RQU) MOV (R4),R2 ;PNT. R2 AT 1ST Q ENTRY MOV 2(R4),TEMP ;SAVE LAST QUE ENTRY ADDR IN TEMP MOV #RQU,2(R2) ;PNT. BACK PTR. AT LISTHEAD MOV TEMP,R2 ;PNT. R2 AT LAST Q ENTRY MOV #RQU,(R2) ;PNT. FORW. PTR. AT LISTHEAD MOV (R4),RQU ;RESTORE NEW LISTHEAD (RQU) MOV 2(R4),RQU+2 ; ; FLUSH I/O REQ NODES FOR TASK IN INTERNAL WRITE REQ QUEUE ; MOV WQU,(R4) ;PUT WRITE Q LISTHEAD IN HANDLER MOV WQU+2,2(R4) ;I/O Q LISTHEAD MOV (R4),R2 ;POINT R2 AT FIRST QUE ENTRY MOV 2(R4),TEMP ;SAVE LAST QUE ENTRY ADDR IN TEMP MOV #60000+H.IOQ,2(R2) ;POINT BACK PTR AT NEW LISTHEAD MOV TEMP,R2 ;POINT R2 AT LAST QUE ENTRY MOV #60000+H.IOQ,(R2) ;POINT FORW. PTR AT NEW LISTHEAD CALL ..FLSH ;FLUSH NODES ;UPDATE WRITE Q LISTHEAD (WQU) MOV (R4),R2 ;PNT. R2 AT 1ST Q ENTRY MOV 2(R4),TEMP ;SAVE LAST QUE ENTRY ADDR IN TEMP MOV #WQU,2(R2) ;PNT. BACK PTR. AT LISTHEAD MOV TEMP,R2 ;PNT. R2 AT LAST Q ENTRY MOV #WQU,(R2) ;PNT. FORW. PTR. AT LISTHEAD MOV (R4),WQU ;RESTORE NEW LISTHEAD (WQU) MOV 2(R4),WQU+2 ; MOV IOQSAV,(R4) ;RESTORE HANDLER I/O Q LISTHEAD MOV IOQSAV+2,2(R4) TST (SP)+ ;RESTORE STACK (NO NEED TO TST (SP)+ ; RESET APR3--NOT USED) ; ; DO COMPLETION ON KILL OR RUNDOWN NODE ; CLR R2 ;ZERO ADJUSTMENT TO DECREMENT MOV #IS.SUC,R3 ;SET STATUS TO SUCCESS CLR R4 ;SET # BYTES XFERED=0 CALL ..IODN CLR ERNA ;ZERO EXPRESS RNA IN UIT JMP IDLE ;GO IDLE ;;;;;;;;;; ; UNLOAD CODE ;;;;;;;;; DOUNL: MOV #UIT,R0 ;UIT ADDR IN R0 (..DNRC CALL) CLR R2 ;SET ADJUSTMENT TO DECREM. 0 MOV #IE.ABO,R3 ;TERMINATION ERROR IN R3 ; ; TERMINATE REQUESTS IN INTERNAL READ QUEUE ; 10$: MOV RQU,R1 ;POINT R1 AT 1ST Q ENTRY CMP #RQU,R1 ;LAST NODE? BEQ 20$ ;YES, BRANCH MOV R1,R4 ;POINT R4 AT NODE FOR ..NDEL CALL ..NDEL CLR R4 ;CLR 2ND WORD OF IOSB CALL ..IODN ;DO COMPLETION FOR THIS NODE BR 10$ ; ; TERMINATE REQUESTS IN INTERNAL WRITE QUEUE ; 20$: MOV WQU,R1 ;POINT R1 AT 1ST Q ENTRY CMP #WQU,R1 BEQ 30$ ;YES, BRANCH MOV R1,R4 ;POINT R4 AT NODE FOR ..NDEL CALL ..NDEL ;DELETE NODE CLR R4 ;CLR 2ND WORD OF IOSB CALL ..IODN ;DO COMPLETION FOR THIS NODE BR 20$ ;GET ANOTHER ; ; CLEAN UP AND DECLARE HANDLER NONRESIDENT ; 30$: CALL ..DNRC JMP EXIT ;GO EXIT .PAGE .SBTTL REPORT ERROR ; ; ON ENTRY R1 CONTAINS RNA ; R3 CONTAINS ERROR CODE ; ERROR: CLR R2 ;SET ADJUSTMENT TO DECREMENT 0 CLR R4 ;SET WORD COUNT 0 CALL ..IODN ;DO COMPLETION BIT #RF.XR,R.FC(R1) ;TEST IF EXPRESS REQUEST BNE 10$ ;YES, BRANCH CLR NRNA ;ZERO NORMAL REQUEST RNA IN UIT JMP IDLE ;RETURN TO IDLE 10$: CLR ERNA ;ZERO EXPRESS REQUEST RNA IN UIT JMP IDLE ;RETURN TO IDLE .PAGE .SBTTL EXIT EXIT: EXIT$S ; ; .PAGE .SBTTL UNIT IDENTIFICATION TABLE (UIT) UIT: ; ; UIT HEADER ; .WORD DSPTBL ;DISPATCH TABLE ADDRESS .BYTE 1 ;MAX NO. UNITS .BYTE 0 ;ACTUAL NO. UNITS .BYTE 0 ;UNIT NO. OF LAST NORMAL REQ .BYTE 0 ;UNIT NO. OF LAST EXPRESS REQ .WORD 0 .WORD 0 ; ; UNIT 0 ENTRY ; .WORD 0 ;UNIT NO. NRNA: .WORD 0 ;PTR TO CURRENT NORM REQ NODE ERNA: .WORD 0 ;PTR TO CURRENT EXPR REQ NODE .PAGE .SBTTL DISPATCH TABLE DSPTBL: ; ; TABLE HEADER ; .WORD 0 ;NOT USED BY THIS HANDLER .WORD 0 ;NOT USED BY THIS HANDLER ; ; FNC CODE 0 (SPECIAL FUNCTION) ; .BYTE 0,0 ;NOT USED BY THIS HANDLER .WORD SPECL ;PTR TO SPECIAL FNC PROCESSOR ; ; FNC CODES 1-20 ARE ILLEGAL ; .REPT 20 .BYTE 0,0 ;NOT USED BY THIS HANDLER .WORD ILLGL ;PTR TO ILLEGAL FNC PROCESSOR .ENDR ; ; FNC CODE 21 (READ VIRTUAL BLOCK) ; .BYTE 0,140 ;SUBFNC=0,EXPRESS BIT=0 .WORD READ ;PTR TO READ FNC PROCESSOR ; ; FNC CODE 22 (WRITE VIRTUAL BLOCK) ; .BYTE 0,140 ;SUBFNC=0,EXPRESS BIT=0 .WORD WRITE ;PTR TO WRITE FNC PROCESSOR .PAGE .SBTTL HANDLER LOCAL DATA BASE ; ; READ AND WRITE REQUEST QUEUE LIST HEADS ; RQU: ;READ REQUEST QUEUE LISTHEAD .WORD RQU .WORD RQU WQU: ;WRITE REQUEST QUEUE LISTHEAD .WORD WQU .WORD WQU ; ; LOCAL DATA ; MB: .ASCII /MB/ ;DEVICE NAME (MB=MAILBOX) TT: .ASCII /TT/ ;TERMINAL DEVICE NAME MAXFNC: .BYTE 22 ;MAXIMUM LEGAL FUCNTION CODE TTNO: .BYTE 0 ;TT NO.+1 FOR REFERENCED TASK TTNOA: .BYTE 0 ;TT NO.+1 FOR REQUESTING TASK FLGS: .BYTE 0 ;I/O REQ FLAGS PARAM CHKINS: .BYTE 001 ;"CHECK FOR INSTALLED TASK" BIT MASK CHKMAT: .BYTE 002 ;"NO MATCH = FATAL" BIT MASK LOCFLG: .BYTE 0 ;LOCAL UTILITY FLAG MXTTP1: .BYTE 0 ;MAX TT UNIT NO.+1 .EVEN UNLFLG: .WORD 0 ;UNLOAD FLAG RWFLAG: .WORD 0 ;RD/WR FLAG (0=READ,1=WRITE) SCANHD: .WORD 0 ;ADDR OF MATCH-SCAN LISTHEAD MATCH: .WORD 0 ;FLAG WORD FOR I/O REQ MATCH RNA: .WORD 0 ;SAVED RNA (REQ NODE ADDRESS) PADDR1: .BLKW 2 ;SAVED PHYS.ADDR. FROM REQ NODE PADDR2: .BLKW 2 ;SAVED PHYS.ADDR. FROM COMPL.NODE BCNT: .WORD 0 ;SAVED BYTE COUNT FOR TRANSFER IOQSAV: .BLKW 2 ; 2 WORDS TO SAVE HANDLER IOQ LISTHEAD TEMP: .WORD 0 ;TEMPORARY STORAGE ; .END INIT EXIT: