.TITLE RPOI - REQUEST & PASS OCB'S FOR MV3.2/M+V1.0 .IDENT /032284/ .ENABL LC .ENABL GBL .NLIST BEX ; ;+ ;***** ; ; RPOI - Provides support for a psuedo "REQUEST-AND-PASS- ; OFFSPRING-INFORMATION" directive for use with RSX-11M V3.2 and ; RSX-11Mplus V1.0 alternate CLI support. ; ; Basic logic consists of: ; 1) Raise priority of task to block execution of almost ; all other tasks (eg. TKTN); controlled by definition ; of "HI$PRI" ; 2) Perform a normal "spawn" on the target ; 3) Re-link associated/specified offspring control block(s), ; if any, from current task to the new offspring task ; 4) Restore task priority and return/exit ; ; CALL SEQUENCE: ; CALL $RPOI$ ; with: ; R5 = address of pseudo RPOI$ "directive parameter block" ; defining: ; 1) Valid SPWN$ DPB with appropriate information ; defined to spawn target task ; 2) RAD50 name of parent task whose offspring ; connection should be passed to target task ; 3) Control flags word; specifies exit-on-completion, ; and pass-all or pass-first OCB ; 4) RAD50 run-time name of target task (currently ; unsupported) ; 5) Address (in pool) of OCB to pass to target ; ;***** ; ; PAUL SORENSON ; AEP/Interactive Graphics Section ; Columbus, OH ; ;***** ; ; Update 3/22/84 -- PRS; modify CCL V9.1 SPAWN to handle more ; general RPOI$ function ; Update 1/2/85 -- PRS; reflect changes RPOI$ macro ; ;***** ;- .MCALL ALTP$,TCBDF$,PKTDF$,DIR$ .MCALL RPOI$ TCBDF$ ;DEFINE TCB SYMBOLS PKTDF$ ; AND OCB SYMBOLS C.LGTH=M$$CRB-5. ; Define max command line length excluding ; the implied terminator HI$PRI=247. ; Highest priority to run at ESC=33 ;MISC. ASCII CONSTANTS REQUIRED CR=15 ; ;***** ; .PSECT $IDATA,RW,D,CON,LCL,REL ALTPRI: ALTP$ , ; Alter priority DPB TEMP: .BLKB 4 ; WORK SPACE DEFPRI: .WORD 0 ; Task's priority when called DPBADR: .WORD 0 ; Place for DPB pointer OFSTCB: .WORD 0 ; Place to save offspring's TCB address ULKOCB: .WORD 0 ; Points to OCB PRECEEDING the OCB being ; un-linked from our offspring's queue LNKOCB: .WORD 0 ; Points to OCB PRECEEDING the OCB in our queue ; to be linked into the offspring's queue MUNAM: .BLKW 2 ; Place for multi-user task name...xxxTnn ; ;***** ; .PSECT $PCODE,RO,I,CON,LCL,REL $RPOI$==. ; GLOBAL ENTRY POINT RPOI$ ; DEFINE SYMBOLIC OFFSETS ; .=$RPOI$ ; RESET LOCATION TO OVER WRITE RPOI$ DPB MOV R5,DPBADR ; Save pointer to DPB CLR LNKOCB ; SHOW HAVEN'T FOUND OCB OF OUR PARENT... CLR ULKOCB ; ...OR OUR OCB IN OFFSPRING CLR ALTPRI+A.LTPR ; SHOW HAVEN'T CHANGED PRIORITY MOV R.POTK(R5),MUNAM ; SAVE TARGET TASK NAME BNE 1$ ; BRANCH IF DEFINED MOV #IE.INS,@#$DSW ; SETUP ERROR CODE JMP EXIT ; AND EXIT 1$: MOV R.POTK+2(R5),MUNAM+2 ; SAVE 2ND HALF OF NAME ; CALL $SWSTK,100$ ; SWITCH TO SYSTEM STATE MOV $TKTCB,R4 ;; PICKUP OUR TCB ADDRESS MOVB T.PRI(R4),DEFPRI ;; SAVE CURRENT PRIORITY...SEE COMMENTS ;; @ EXIT CMP R.POTK(R5),#^R... ;; TARGET TASK USING PROTO-TYPE NAME ?? BNE 20$ ;; BRANCH IF NO MOV #TEMP,R3 ;; PICKUP PLACE TO BUILD MULTI-USER TASK NAME MOV R.PODV(R5),R0 ;; PICKUP DEVICE NAME BEQ 4$ ;; BRANCH IF UNDEFINED, USE TI: CMP R0,#"TI ;; EXPLICITLY USE TI: ?? BNE 10$ ;; BRANCH IF NO 4$: MOVB #'T,(R3)+ ;; SET FIRST CHARACTER FOR MULTI-USER TASK NAME MOV T.UCB(R4),R0 ;; PICKUP OUR TI: UCB POINTER 5$: MOV U.RED(R0),R0 ;; FOLLOW REDIRECTS, JUST IN CASE CMP U.RED(R0),R0 BNE 5$ MOV U.DCB(R0),R2 ;; GET DCB ADDRESS SUB D.UCB(R2),R0 ;; COMPUTE RELATIVE UCB ADDRESS BEQ 8$ ;; BRANCH IF 1ST UNIT MOV D.UCBL(R2),R1 ;; GET UCB LENGTH CALL $DIV ;; COMPUTE RELATIVE UNIT # 8$: MOVB D.UNIT(R2),R2 ;; GET 1ST UNIT # ADD R0,R2 ;; COMPUTE PHYSICAL UNIT # BR 12$ ;; PICKUP WITH BINARY TO ASCII CONVERSION ; 10$: MOVB R0,(R3)+ ;; SAVE 1ST CHARACTER OF PHYSICAL DEV. NAME MOV R.POUN(R5),R2 ;; PICKUP UNIT # 12$: BEQ 18$ ;; BRANCH IF 0 MOV R2,R1 ;; COPY UNIT # BIC #177407,R1 ;; GRAB HI-ORDER UNIT # BEQ 17$ ;; BRANCH IF 0 ASR R1 ;; RE-ALIGN HI UNIT # ASR R1 ASR R1 CMP R1,#10 ;; UNIT # > 77 ?? BLT 15$ ;; BRANCH IF NO ADD #11,R1 ;; ALLOW M+ TERMINALS A0-X7 15$: ADD #60,R1 ;; MAKE IT ASCII MOVB R1,(R3)+ ;; AND SAVE IT 17$: BIC #177770,R2 ;; GET LO-ORDER UNIT # 18$: ADD #60,R2 ;; MAKE IT ASCII MOVB R2,(R3)+ ;; AND SAVE IT CLRB (R3) ;; SET TERMINATOR MOV #TEMP,R0 ;; GET START ADDRESS AGAIN CALL $CAT5 ;; CONVERT IT TO RAD50 MOV MUNAM+2,MUNAM ;; REPLACE "..." WITH 2ND 1/2 OF NAME MOV R1,MUNAM+2 ;; SAVE "Tnn" AS NEW 2ND 1/2 OF NAME ; 20$: MOV R5,R3 ;; COPY DPB ADDRESS ADD #R.POTK,R3 ;; POINT TO TARGET TASK NAME CALL $SRSTD ;; SEARCH FOR TARGET TCB BCC 28$ ;; BRANCH IF FOUND MOV #IE.INS,R0 ;; ELSE, PICKUP ERROR CODE BR 99$ ;; AND EXIT 28$: BIT #T3.CLI,T.ST3(R0) ;; TARGET A CLI ?? BEQ 38$ ;; BRANCH IF NO BIT #RP.OAL,R.POSC(R5) ;; PASS ALL OCB CONNECTIONS ?? BEQ 34$ ;; BRANCH IF NO, OKAY MOV #IE.ITS,R0 ;; ELSE, PICKUP ERROR CODE BR 99$ ;; AND EXIT 34$: TST R.POBL(R5) ;; COMMAND FOR CLI GIVEN ?? BNE 38$ ;; BRANCH IF YES, OKAY MOV #IE.INS,R0 ;; ELSE, PICKUP ERROR CODE BR 99$ ;; AND EXIT 38$: ; 40$: MOV R.POOA(R5),R0 ;; PICKUP ANY OCB ADDRESS MOV R5,R1 ;; COPY DPB ADDRESS ADD #R.POPT,R1 ;; POINT TO PARENT NAME MOV R4,R2 ;; COPY TCB ADDR ADD #T.OCBH,R2 ;; POINT TO START OF OCB QUEUE TST R0 ;; SPECIFIC OCB GIVEN ?? BNE 50$ ;; BRANCH IF YES, FIND OCB TST (R1) ;; SPECIFIC PARENT TASK GIVEN ?? BNE 50$ ;; BRANCH IF YES,FIND OCB BIT #RP.ONX!RP.OAL,R.POSC(R5) ;; ANY SPECIAL OCB HANDLING ?? BEQ 70$ ;; BRANCH IF NO, NO OCB RE-LINKING MOV R2,LNKOCB ;; ELSE, POINT TO HEAD OF OCB IN QUEUE BR 70$ ;; AND EXIT ; 50$: BIT #RP.ONX!RP.OAL,R.POSC(R5) ;; ANY SPECIAL OCB HANDLING ?? BEQ 54$ ;; BRANCH IF NO, OKAY MOV #IE.ALG,R0 ;; ELSE, PICKUP ERROR CODE BR 99$ ;; AND EXIT 54$: BIT #T3.CLI,T.ST3(R4) ;; ONLY CLI'S ALLOWED HERE BNE 60$ ;; BRANCH IF OK MOV #IE.ITS,R0 ;; ELSE, FLAG ERROR BR 99$ ;; AND EXIT ; *** SCAN OCB QUEUE FOR SPECIFIC OCB/PARENT TASK 60$: MOV R2,R4 ;; COPY OCB ADDRESS MOV (R4),R2 ;; PICKUP LINK TO NEXT OCB BNE 63$ ;; BRANCH ON VALID OCB MOV #IE.ALG,R0 ;; END-OF-QUEUE, SETUP ERROR CODE BR 99$ ;; AND EXIT 63$: TST R0 ;; SPECIFIC OCB ADDR GIVEN ?? BEQ 65$ ;; BRANCH IF NO, CHECK NAME CMP R0,R2 ;; ELSE, ADDRESSES MATCH ?? BNE 60$ ;; BRANCH IF NO, CHECK NEXT OCB 65$: TST (R1) ;; PARENT NAME GIVEN ?? BEQ 68$ ;; BRANCH IF NO CMP O.STAT(R2),(R1) ;; PARENT TASK NAMES MATCH ?? BNE 60$ ;; BRANCH IF NO, CHECK NEXT OCB CMP O.STAT+2(R2),2(R1) ;; MAYBE ?? BNE 60$ ;; BRANCH IF NO, CHECK NEXT OCB 68$: MOV R4,LNKOCB ;; ELSE, SAVE POINTER TO OCB TO RE-LINK 70$: ; 98$: MOV #IS.SUC,R0 ;; SUCCESSFUL EXIT ; 99$: MOV R0,@#$DSW ;; SAVE STATUS RETURN ;; BACK TO TASK STATE TST @#$DSW ; SUCCESS ?? BPL 100$ ; BRANCH IF YES JMP EXIT ; ELSE, EXIT ; ;+ ;***** ; ; Time to grab the system via task priority; we will do ; normal SPWN$ find the OCB queued by the exec then re-link ; the correct parent to the new offspring and get out of the ; way (hopefully). ;***** ;- ; 100$: MOV #HI$PRI,ALTPRI+A.LTPR ; RAISE OUR PRIORITY DIR$ #ALTPRI ADD #R.POSD,R5 ; POINT TO SPWN$ DPB IN RPOI$ BLOCK DIR$ R5 ; PERFORM A "SPWN$" BCS EXIT ; BRANCH IF SPAWN FAILS ; CALL $SWSTK,160$ ; Switch to system state MOV #MUNAM,R3 ;; Point to offspring's name ;; always scan for xxxTnn 1st 110$: CALL $SRSTD ;; Search installed tasks for target BCC 112$ ;; Branch if offspring found ; .IFNDF R$$MPL ;; Under M, rescan STD for "...xxx" CMP (R3),^R... ;; Already looked for ...xxx ?? BEQ 111$ ;; Branch is yes, bad error MOV DPBADR,R3 ;; Point to ...xxx in RPOI$ parameter block ADD #R.POTK,R3 BR 110$ ;; And look again .ENDC ;R$$MPL 111$: MOV #IE.INS,@#$DSW ;; Flag error as task not installed... BR 159$ ;; should never happen if SPWN$ worked ; 112$: MOV R0,R4 ;; Save our child's TCB address ADD #T.OCBH,R0 ;; Point to child's OCB list head CLR R2 ;; Show no OCB yet MOV $TKTCB,R5 ;; Pickup our TCB address 116$: MOV (R0),R1 ;; Pickup next OCB queued to child BEQ 120$ ;; Branch on last OCB CMP O.PTCB(R1),R5 ;; OCB point to us ?? BNE 118$ ;; Branch if no, check next MOV R0,R2 ;; Save address of preceeding OCB MOV R1,R3 ;; and OCB to re-link 118$: MOV R1,R0 ;; Step to next OCB BR 116$ ;; Loop til done ; ; *** Should now have most recent OCB queued by this task to offspring, this ; will be removed and our parent's OCB inserted instead ; 120$: TST R2 ;; Found our OCB in offspring ?? BNE 125$ ;; Branch if yes MOV #IE.MAP,@#$DSW ;; Flag error, very bad BR 159$ ;; and exit 125$: MOV LNKOCB,R0 ;; Pickup pointer to OCB pointing to ;; parent's OCB to re-link BEQ 127$ ;; Branch if nothing to re-link MOV (R0),R1 ;; Point to OCB(s) being re-linked BNE 130$ ;; Branch if defined 127$: MOV (R3),(R2) ;; No parent, pull our OCB from offspring BNE 140$ ;; Branch if not last OCB MOV R2,T.OCBH+2(R4) ;; Close offspring's OCB list BR 140$ ;; Branch to finish up ; ; *** Found our parent...pass it on to our child by replacing the ; OCB we queued via the SPAWN directive with our parent's ; OCB. NOTE: some undocumented information is passed in the ; OCB status words for CLI'S; see comment's below ; 130$: MOV O.MCRL(R3),O.MCRL(R1) ;; Update command line address MOV O.STAT+4(R3),O.STAT+4(R1) ;; Copy CLI specific MOV O.STAT+6(R3),O.STAT+6(R1) ;; information (UIC's) MOV R1,(R2) ;; Re-link parent's OCB to offspring MOV DPBADR,R2 ;; Pickup DPB pointer MOV R.POSC(R2),R2 ;; Get flags word BIT #RP.OAL,R2 ;; Pass all OCB's ?? BEQ 135$ ;; Branch if no 133$: TST (R1) ;; Else, skip to end-of-list BEQ 135$ ;; in our OCB queue MOV (R1),R1 BR 133$ 135$: MOV (R1),(R0) ;; Un-link parent's OCB from our list BNE 137$ ;; Branch if not empty MOV R0,T.OCBH+2(R5) ;; Else, close our list 137$: MOV (R3),(R1) ;; Re-link rest of offspring's OCB's ;; to new set BNE 139$ ;; Branch if not empty MOV R1,T.OCBH+2(R4) ;; Else, close offspring's list 139$: ; ; *** Propagate our T3.MCR bit...if child's a CLI, must do it via ; command line terminator. ; 140$: BIT #T3.CLI,T.ST3(R4) ;; Child a CLI ?? BEQ 145$ ;; Branch if no BIT #T3.MCR,T.ST3(R5) ;; Do we prompt on exit ?? BEQ 150$ ;; Branch if no, almost done MOV O.MCRL(R3),R0 ;; Else, pickup command line address ADD #4,R0 ;; Skip link & TCB address MOV DPBADR,R1 ;; Pickup DPB address ADD R.POBL(R1),R0 ;; Offset to end-of-command MOVB #CR,(R0) ;; Change terminator to carriage return BR 150$ ;; Branch to finish 145$: BIT #T3.MCR,T.ST3(R5) ;; Propagate our T3.MCR bit BEQ 149$ BIS #T3.MCR,T.ST3(R4) ;; Have child prompt BR 150$ ;; Branch to finish up 149$: BIC #T3.MCR,T.ST3(R4) ;; Have child exit silently ; ; *** Wayward packet sitting in pool @ R3, must now deallocate it ; 150$: MOV R3,R0 ;; Copy pointer MOV #O.LGTH,R1 ;; Define size of packet CALL $DEACB ;; Deallocate it to free pool DEC T.RDCT(R5) ;; Decrement our offspring count BIC #T3.MCR,T.ST3(R5) ;; we will exit quietly MOV DPBADR,R0 ;; Get DPB pointer MOV R.POSC(R0),R0 ;; Pickup flags word BIT #RP.OEX,R0 ;; Exit on completion ?? BEQ 159$ ;; Branch if no JMP $DREXT ;; Force task exit 159$: RETURN ;; Back to task state ; ; *** ALL DONE...We will now drop our priority back to what it was when ; we were called. Why, you ask? When playing games with queueing ; command lines directly to a task, the caller (CCL) may already have ; pushed its priority up, so we better not drop to the task's ; installed priority least we screw up some task synchronization. ; 160$: EXIT: MOV @#$DSW,-(SP) ; Save return status TST ALTPRI+A.LTPR ; Altered our priority ??? BEQ 5$ ; Branch if no MOVB DEFPRI,ALTPRI+A.LTPR ; Setup to drop priority DIR$ #ALTPRI ; do it 5$: CLC ; Assume success MOV (SP)+,@#$DSW ; Restore status BPL 10$ ; Branch on success SEC ; Else, flag error in carry bit too 10$: RETURN ; Return to caller .END