.TITLE GCCI - GET COMMAND FOR COMMAND INTERPRETER .IDENT /010385/ .ENABL GBL .ENABL LC .NLIST BEX ; ;+ ;***** ; ; GCCI - defines a psuedo "GET-COMMAND-FOR-COMMAND-INTERPRETER" ; directive to use with RSX-11M V3.2/ RSX-11Mplus V1.0 alternate ; CLI support. NOTE: 2 special types of command packets are ; recognized and trapped by this routine; 1) packets with odd ; address for TI's UCB are null length packets and cause ; the default prompt for the CLI to be sent to TI:, 2) task's ; exitting with T3.REM bit set will send the CLI a "REM taskname" ; command terminated by an escape (ASCII "33) which will be sent ; directly to MCR. Currently, neither of these 2 command packets ; will be returned to the caller. ; ; CALL SEQUENCE: ; CALL $GCCI$ ; with: ; R5 pointing to a "directive parameter block" which ; defines: ; 1) address of command buffer ; 2) length in bytes of command buffer (must be ; at least 11 bytes for misc. control stuff) ; 3) address of optional information buffer ; 4) length of information buffer (or 0) ; 5) control flags word ; NOTE: See GCCI$ macro for definition of physical ; position within parameter block of variables ; ;***** ;- ; ; *** NOTES: Requires defn of symbol TI$LUN and TI$EFN for resolving lun ; and event flag to use when send default prompt to TI:. To avoid ; problems of issuing prompts to a terminal locked in hold-screen ; mode, the special routine "$TIQIO" is called to issue a write ; or time-out function. This may be called by others if they need ; similar functionality. ; ;***** ; ; Paul Sorenson ; AEP/Interactive Graphics Section ; Columbus, OH 43214 ; ;***** ; ; Update 4/10/84 -- prs; add "$CIQIO" routine ; Update 1/3/85 -- PRS; Reflect changes in GCCI$ macro, add support ; for returning specific command packets; move ; $CIQIO functionality to its own module "$TIQIO" ; ;***** ;- ; CR=15 ; ASCII CARRIAGE RETURN ESC=33 ; ASCII ESCAPE EFN1=1 ; EFN FOR QIO EFN2=2 ; EFN FOR MARK TIME EF1MSK=1 ; MASK WORD FOR EFN 1 EF2MSK=2 ; MASK WORD FOR EFN 2 ; .MCALL DIR$,QIOW$,ALUN$,DCBDF$,UCBDF$,TCBDF$,PKTDF$ .MCALL WTLO$,MRKT$,QIO$,CMKT$S,CLEF$S,WTSE$S .MCALL CCBDF$,GCCI$ ; ALTERNATE CLI MACROS NEEDED CCBDF$ ; DEFINE VARIOUS CONTROL BLOCK OFFSETS DCBDF$ PKTDF$ TCBDF$ UCBDF$,,TTDEF ; ; *** LOCAL VARIABLES/DPB'S ; .PSECT $IDATA,RW,D,LCL,CON,REL OCBADR: .WORD 0 ; OCB PACKET ADDRESS ASSOC WITH PKTADR PKTADR: .WORD 0 ; ADDRESS OF COMMAND PACKET POINTING TO ; PACKET TO BE OPERATED ON !!!! ASNLUN: ALUN$ TI$LUN,TI,0 ; ASSIGN LUN TO TI: ; ; *** ; .PSECT $PCODE,RO,I,LCL,CON,REL $GCCI$==. ; GLOBAL ENTRY POINT GCCI$ ; DEFINE OFFSETS WITHIN GCCI$ PARAMETER BLOCK ; .=$GCCI$ ; OVERWRITE GCCI$ PARAMETER BLOCK WITH CODE CALL $SAVAL ; SAVE ALL REGISTERS MOV G.CCBA(R5),R4 ; PICKUP COMMAND BUFFER ADDRESS BEQ 15$ ; BRANCH IF UNDEFINED, ERROR CMP R4,#120000 ; IN EXEC SPACE ?? BLO 15$ ; BRANCH IF YES, ERROR MOV G.CCBL(R5),R3 ; PICKUP LENGTH OF COMMAND BUFFER SUB #G.CCBF,R3 ; AT LEAST ENOUGH FOR 1 CHARACTER ?? BLE 15$ ; BRANCH IF NO, ERROR MOV #G.CCBF/2,R0 ; DEFINE # WORDS TO CLEAR 8$: CLR (R4)+ ; CLEAR FIRST PART OF BUFFER SOB R0,8$ MOV R4,R0 ; COPY CURRENT ADDRESS IN BUFFER ADD R3,R0 ; OFFSET TO END OF BUFFER TSTB -(R0) ; THIS WILL TRAP IF ILLEGAL ADDRESS MOVB R3,(R4) ; SAVE LENGTH IN 1ST BYTE, TEMPORARILY MOV G.CCIA(R5),R0 ; PICKUP INFO BUFFER ADDRESS MOV G.CCIL(R5),R1 ; AND LENGTH BEQ 19$ ; BRANCH IF NOT DEFINED, OKAY BLT 15$ ; BRANCH IF ILLEGAL LENGTH, ERROR CMP R0,#120000 ; IN EXEC SPACE ?? BHIS 17$ ; BRANCH IF NO, CHECK LAST ADDRESS 15$: MOV #IE.ADP,@#$DSW ; SET ERROR RETURN CODE JMP 132$ ; AND GET OUT 17$: ADD R1,R0 ; OFFSET TO END OF INFO BUFFER TSTB -(R0) ; TRAP ILLEGAL ADDRESS 19$: MOV R5,R3 ; FREE R5 FOR TASK'S TCB POINTER ; ;+ ;***** ; ; SWITCH TO SYSTEM STATE TO FILLIN THE COMMAND AND INFORMATION ; BUFFERS. ON ENTRY TO SYSTEM STATE, R3 POINTS TO THE PARAMETER ; BLOCK PASSED TO $GCCI$, AND R4 POINTS TO THE START OF COMMAND ; TEXT AREA IN THE CLI TASK'S COMMAND BUFFER: ; ; !-----------------------------------! ; ! ASCII device name of TI: ! ; !-----------------------------------! ; ! # chars. returned ! Unit # of TI: ! ; !-----------------------------------! ; ! # characters in command line ! ; !-----------------------------------! ; ! Status ! Command terminator! ; !-----------------------------------! ; ! Start of command text ! <-- R4 ; ! ! ; ; ON RETURN TO USER STATE, ERROR/SUCCESS CODE IS IN $DSW ; ;***** ;- 20$: CALL $SWSTK,110$ ; GET TO SYSTEM STATE MOV $TKTCB,R5 ;; PICKUP OUR TCB ADDRESS BIT #T3.CLI,T.ST3(R5) ;; TASK A CLI ?? BEQ 24$ ;; BRANCH IF NO 22$: MOV T.RCVL(R5),R2 ;; GET CLI CONTROL BLOCK ADDRESS BNE 26$ ;; BRANCH IF DEFINED 24$: MOV #IE.PRI,R0 ;; BAD ERROR, NOT INIT. AS CLI TASK BR 39$ ;; AND EXIT 26$: BIC #T3.MCR,T.ST3(R5) ;; BLOCK TASK PROMPT ON EXIT TST (R2) ;; ANY COMMANDS IN QUEUE ?? BEQ 30$ ;; BRANCH IF NO MOV G.CCAD(R3),R0 ;; SPECIFIC COMMAND PACKET REQUESTED ?? BEQ 40$ ;; BRANCH IF NO, USE 1ST IN QUEUE 28$: CMP (R2),R0 ;; NEXT PACKET THE RIGHT ONE ?? BEQ 40$ ;; BRANCH IF YES, USE IT MOV (R2),R2 ;; STEP TO NEXT PACKET BNE 28$ ;; LOOP IF MORE IN QUEUE ;; ;; *** NO COMMAND, OR DESIRED COMMAND NOT IN QUEUE...ACTION CONTROLLED BY ;; "NCP" FLAG BITS ;; 30$: BIT #GC.CST,G.CCNC(R3) ;; STOP ON NO COMMAND ?? BEQ 36$ ;; BRANCH IF NO BIT #T2.AST,T.ST2(R5) ;; TASK IN AST STATE ?? BEQ 34$ ;; BRANCH IF NO, OKAY TO STOP MOV #IE.AST,R0 ;; ELSE, SET ERROR CODE BR 39$ ;; AND EXIT 34$: CALL $STPCT ;; STOP OURSELVES MOV #IS.CLR,R0 ;; SET SPECIAL RETURN CODE BR 39$ ;; AND EXIT 36$: BIT #GC.CEX,G.CCNC(R3) ;; EXIT ON NO COMMAND ?? BEQ 38$ ;; BRANCH IF NO JMP $DREXT ;; EXIT TASK 38$: MOV #IE.ITS,R0 ;; ONLY THING LEFT IS RETURN ERROR CODE 39$: JMP 109$ ;; AND EXIT ;; ;; *** COMMAND PACKET ADDRESS IN R2 POINTS TO PACKET TO BE RETURNED. ;; COMMAND PACKETS CONSISTS OF LINK WORD, TI:UCB ADDRESS, AND ;; COMMAND STRING (PROVIDED BIT 0 IN UCB IS CLEAR); ALSO FIND ANY ;; OCB ATTACHED TO COMMAND PACKET ;; 40$: MOV R2,PKTADR ;; SAVE PACKET ADDRESS POINTING TO ;; DESIRED PACKET FOR RE-LINKING QUEUE MOV (R2),R2 ;; POINT TO COMMAND PACKET MOV T.OCBH(R5),R0 ;; PICKUP OCB LIST HEAD BEQ 45$ ;; BRANCH IF EMPTY 43$: CMP O.MCRL(R0),R2 ;; OCB BELONG TO THIS COMMAND ?? BEQ 45$ ;; BRANCH IF YES MOV (R0),R0 ;; STEP TO NEXT OCB BNE 43$ ;; BRANCH IF MORE 45$: MOV R0,OCBADR ;; SAVE COMMAND'S OCB PACKET ADDR TST (R2)+ ;; SKIP OVER LINK WORD MOV (R2)+,R0 ;; GET UCB BICB #GC.CTE!GC.CNL,G.CCFL-G.CCBF(R4) ;; ASSUME IT'S A FULL COMMAND ASR R0 ;; CHECK LSB IN UCB .IFDF R$$MPL ;; M+ EXEC HANDLES REMOVES DIRECTLY BCC 50$ ;; BRANCH ON C-BIT CLEAR, FULL COMMAND .IFF ;R$$MPL ;; M EXEC QUEUES "REM taskname" COMMAND TO CLI BCS 48$ ;; BRANCH ON C-BIT SET, PROMPT PACKET CALL REMCHK ;; CHECK FOR EXECUTIVE "REM" COMMAND BCS 22$ ;; BRANCH IF COMMAND REQUEUED TO MCR... BR 50$ ;; C-BIT CLEAR, CONT. PROCESSING .ENDC ;R$$MPL 48$: BISB #GC.CTE!GC.CNL,G.CCFL-G.CCBF(R4) ;; SET FLAGS INDICATING CLC ;; THIS IS A 4 WORD PROMPT PACKET (NO WAY TO ;; TELL IF IT'S NULL LINE OR TASK EXIT) 50$: ASL R0 ;; RECOVER VALID UCB ADDRESS MOV R0,T.UCB(R5) ;; SET OUR TCB TO NEW TI: MOV $HEADR,R1 ;; POINT TO OUR HEADER MOV U.LUIC(R0),H.CUIC(R1) ;; RESET TASK'S "CURRENT" UIC MOV U.UIC(R0),H.DUIC(R1) ;; AND "DEFAULT" UIC MOV U.DCB(R0),R1 ;; PICKUP DCB ADDRESS MOV D.NAM(R1),G.CCDV-G.CCBF(R4) ;; SET DEVICE NAME MOVB D.UNIT(R1),G.CCUN-G.CCBF(R4) ;; AND LO-UNIT # SUB D.UCB(R1),R0 ;; ALIGN UCB TO 1ST UCB BEQ 55$ ;; BRANCH IF WE ARE 1ST UNIT MOV D.UCBL(R1),R1 ;; PICKUP UCB LENGTH CALL $DIV ;; COMPUTE RELATIVE UNIT # ADD R0,G.CCUN-G.CCBF(R4) ;; COMPUTE PHYSICAL UNIT # 55$: BITB #GC.CTE!GC.CNL,G.CCFL-G.CCBF(R4) ;; PROMPT ONLY ?? BNE 80$ ;; BRANCH IF YES CLR R0 ;; RETRIEVE SIZE OF COMMAND TEXT BUFFER BISB (R4),R0 MOV R3,-(SP) ;; FREE R3 MOV R2,-(SP) ;; MARK CURRENT PACKET POINTER MOV R4,R3 ;; COPY START OF COMMAND TEXT BUFFER 60$: MOVB (R2)+,R1 ;; PICKUP CHARACTER MOVB R1,(R3)+ ;; PUT IT IN COMMAND TEXT BUFFER 62$: CMPB R1,#CR ;; HIT TERMINATOR ?? BNE 66$ ;; BRANCH IF NO BIS #T3.MCR,T.ST3(R5) ;; YES, REENABLE PROMPT ON EXIT BR 70$ ;; BRANCH TO FINISH UP 66$: CMPB R1,#ESC ;; HIT TERMINATOR ?? BEQ 70$ ;; BRANCH IF YES SOB R0,60$ ;; LOOP FOR MAX # IN USER BUFFER INC R0 ;; USER BUFFER EXHAUSTED, CONTINUE MOVB (R2)+,R1 ;; SCAN OF PACKET FOR TERMINATOR BR 62$ ;; LOOP TIL DONE 70$: MOVB R1,G.CCTC-G.CCBF(R4) ;; SAVE TERMINATOR SUB R4,R3 ;; COMPUTE # CHARACTERS COPIED DEC R3 ;; EXCLUDING TERMINATOR MOVB R3,G.CCCT-G.CCBF(R4) ;; SAVE # CHARS RETURNED SUB (SP)+,R2 ;; COMPUTE TOTAL # CHARS IN DEC R2 ;; POOL PACKET; LESS TERMINATOR MOV R2,G.CCCL-G.CCBF(R4) ;; SAVE IT MOV (SP)+,R3 ;; RECOVER PARAMETER BLOCK POINTER ;; ;; *** IF INFO BUFFER IS DEFINED, TIME TO FILL IN ALL SORTS OF ADDITIONAL ;; STUFF REGARDING COMMAND LINE ;; 80$: MOV G.CCNC(R3),R4 ;; PICKUP FLAGS WORD MOV G.CCIL(R3),R1 ;; RECOVER INFO BUFFER LENGTH ASR R1 ;; ADJUST TO WORD COUNT BEQ 98$ ;; BRANCH IF NO INFO REQUESTED MOV G.CCIA(R3),R0 ;; ELSE, RECOVER BUFFER ADDRESS MOV T.UCB(R5),R3 ;; GET TI:'S UCB ADDRESS MOV U.CW2(R3),(R0)+ ;; SAVE 2ND CHAR. WORD SUB #2,R1 ;; ADJUST FOR NEXT FIELD BLE 98$ ;; BRANCH IF NO ROOM MOV OCBADR,R2 ;; PICKUP OCB ADDRESS BNE 90$ ;; BRANCH IF DEFINED CLR (R0)+ ;; NO PARENT, CLEAR NAME FIELD CLR (R0)+ BR 92$ ;; BRANCH FOR NEXT FIELD 90$: MOV O.STAT(R2),(R0)+ ;; COPY PARENT NAME MOV O.STAT+2(R2),(R0)+ 92$: DEC R1 ;; MORE INFO REQUESTED ?? BLE 98$ ;; BRANCH IF NO MOV R2,(R0)+ ;; SAVE OCB ADDRESS DEC R1 ;; MORE INFO REQUESTED ?? BLE 98$ ;; BRANCH IF NO MOV U.LUIC(R3),(R0)+ ;; FILL IN LOGIN UIC DEC R1 ;; MORE INFO REQUESTED ?? BLE 98$ ;; BRANCH IF NO MOV U.UIC(R3),(R0)+ ;; FILL IN CURRENT UIC DEC R1 ;; MORE INFO REQUESTED ?? BLE 98$ ;; BRANCH IF NO CLR (R0) ;; ASSUME GOING TO DEQUEUE PACKET BIT #GC.CND,R4 ;; CHECK FLAG BIT BEQ 100$ ;; BRANCH IF DEQUEUEING PACKET MOV @PKTADR,(R0) ;; ELSE, FILL IN PACKET ADDRESS BEQ 108$ ;; AND EXIT 98$: BIT #GC.CND,R4 ;; DEQUEUE PACKET ?? BNE 108$ ;; BRANCH IF NO, DONE ;; ;; *** DEQUEUE COMMAND PACKET AND CLEAR ANY REFERENCE TO IT IN OCB ;; 100$: MOV PKTADR,R2 ;; RECOVER ADDRESS OF PREV. PACKET MOV (R2),R0 ;; POINT TO PACKET TO DE-QUEUE MOV (R0),(R2) ;; RELINK QUEUE BNE 104$ ;; BRANCH IF MORE PACKETS MOV R2,T.RCVL+2(R5) ;; ELSE, CLOSE QUEUE LIST 104$: MOV #M$$CRB,R1 ;; ASSUME HAVE FULL COMMAND PACKET ASR 2(R0) ;; TEST UCB ADDRESS FOR PROMPT BIT BCC 106$ ;; BRANCH IF CLEAR MOV #4,R1 ;; ELSE, SET PROMPT PACKET SIZE 106$: CALL $DEACB ;; FINALLY, DEALLOCATE POOL PACKET MOV OCBADR,R0 ;; PICKUP OCB ADDRESS BEQ 108$ ;; BRANCH IF NO PARENT CLR O.MCRL(R0) ;; CLEAR OUT POINTER TO CMD PACKET 108$: MOV #IS.SUC,R0 ;; SETUP RETURN CODE 109$: MOV R0,@#$DSW ;; SAVE RETURN CODE LOCALLY RETURN ;; BACK TO USER STATE 110$: ; REF. LABEL ; ; *** NOW HAVE EVERYTHING NEEDED ; TST @#$DSW ; CHECK ERROR CODE IN DSW BEQ 133$ ; BRANCH IF JUST UNSTOPPED, CARRY CLEAR BLT 132$ ; BRANCH ON ERROR MOV R4,R0 ; COPY POINTER IN COMMAND BUFFER SUB #G.CCBF,R0 ; POINT TO 1ST WORD MOV (R0)+,ASNLUN+A.LUNA ; SETUP DEVICE NAME MOVB (R0)+,ASNLUN+A.LUNU ; AND UNIT # DIR$ #ASNLUN ; ASSIGN IT FOR TASK'S TI: BITB #GC.CTE!GC.CNL,G.CCFL-G.CCBF(R4) ; PROMPT REQUEST ?? BEQ 130$ ; BRANCH IF NO, ALL DONE 120$: MOV $TKTCB,R0 ; PICKUP OUR TCB ADDRESS MOV T.RCVL(R0),R0 ; PICKUP 1ST COMMAND PACKET = CCB BITB #CL.INL!CL.IEX,C.LIST(R0) ; CLI WANTS PROMPT CONTROL ?? BNE 130$ ; BRANCH IF YES, CLI MUST ISSUE PROMPT MOV R0,R1 ; COPY CCB ADDRESS ADD #C.LIPR,R1 ; OFFSET TO START OF PROMPTS 122$: TSTB (R1)+ ; SCAN FOR 1ST NULL BNE 122$ ; LOOP TO END OF CTRL-C PROMPT MOV R1,R0 ; SAVE START ADDRESS OF PROMPT 125$: TSTB (R1)+ ; LOOK FOR NEXT NULL BNE 125$ ; LOOP TO END OF DEFAULT PROMPT SUB R0,R1 ; DETERMINE LENGTH OF PROMPT MOV #20$,-(SP) ; SETUP RETURN POINT JMP $TIQIO ; TRANSFER CONTROL TO QIO ROUTINE ; 130$: CLC ; RETURN CARRY CLEAR BR 133$ ; AND EXIT 132$: SEC ; ERROR, SET CARRY BIT 133$: RETURN ; AND RETURN TO CALLER ; .PAGE .SBTTL LOCAL SUBROUTINES ; .IFNDF R$$MPL ; NEED "REMCHK" ONLY WITH 11M ; ;+ ;***** ; ; REMCHK - CHECKS A COMMAND LINE TO DETERMINE IF ITS A "REM task<33>" ; COMMAND DISPATCHED BY THE EXECUTIVE TASK EXIT ROUTINE FOR THOSE TASK'S ; INSTALLED WITH /RUN=REM OPTION. AS MANY CRITERIA CHECKS AS POSSIBLE ; ARE MADE ON THE COMMAND LINE AND TARGET TASK TO BE SURE THE ; REQUEST WAS MADE BY THE EXECUTIVE "DREIF.MAC" CODE...MUST NOT HAVE ; AN OCB, MUST BE TERMINATED BY AN ESCAPE <33>, MUST HAVE EXACTLY ; 6 CHARACTERS IN TASK NAME (MAY INCLUDE SPACES), TARGET TASK MUST ; HAVE "RUN=REM" FLAG SET IN TCB. ; ; CALL SEQUENCE ; CALL REMCHK ; WITH: ; MUST ALREADY BE IN SYSTEM STATE WITH R5 = TASK'S TCB ; ADDRESS AND R2 = POINTER TO 1ST CHARACTER IN COMMAND STRING. ; ; RETURNS: ; CARRY SET IF "REM task" COMMAND QUEUED TO MCR... ; CARRY CLEAR IF NOT EXECUTIVE "REM task" COMMAND ; ; NOTE: R0/R2/R3/R4/R5 MUST BE SAVED/RESTORED IF USED ; ;***** ;- REMCHK: TST OCBADR ;; HAVE A PARENT ?? BNE 39$ ;; BRANCH IF YES, RETURN WITH CC MOV R0,-(SP) ;; SAVE R0/R3 MOV R3,-(SP) SUB #4,SP ;; RESERVE 2 WORD WORKSPACE ON STACK MOV R2,R0 ;; COPY COMMAND STRING START ADDRESS CMP (R0)+,(PC)+ ;; CHECK FOR "REM " .ASCII /RE/ BNE 35$ ;; BRANCH IF NOT CMP (R0)+,(PC)+ ;; MAYBE .ASCII /M / BNE 35$ ;; BRANCH IF NOT CMPB 6(R0),#ESC ;; MUST BE TERMINATED BY "33 BNE 35$ ;; BRANCH IF NOT MOV #1,R1 ;; ENABLE .'S IN TASK NAME CALL $CAT5 ;; CONVERT IT TO RAD50 BCS 35$ ;; BRANCH IF FAILS, INVALID "REM" MOV R1,(SP) ;; SAVE 1ST 1/2 OF NAME MOV #1,R1 ;; ENABLE .'S IN NAME CALL $CAT5 ;; CONVERT IT TO RAD50 BCS 35$ ;; BRANCH IF FAILS, INVALID "REM" MOV R1,2(SP) ;; SAVE 2ND 1/2 OF NAME MOV SP,R3 ;; POINT R3 TO TASK NAME CALL $SRSTD ;; SEARCH FOR TASK BCS 35$ ;; BRANCH IF NOT FOUND, INVALID "REM" BIT #T3.REM,T.ST3(R0) ;; /RUN=REM OPTION SET ?? BEQ 35$ ;; BRANCH IF NO, INVALID "REM" MOV PKTADR,R2 ;; GET PACKET POINTING TO "REM" PACKET MOV (R2),R1 ;; POINT TO "REM" PACKET MOV (R1),(R2) ;; RE-LINK QUEUE BNE 30$ ;; BRANCH IF MORE IN LIST MOV R2,T.RCVL+2(R5) ;; ELSE, CLOSE LIST 30$: MOV $MCRPT,R0 ;; PICKUP MCR... TCB POINTER CALL $QCLIL ;; REQUEUE LINE TO MCR... SEC ;; SHOW "SUCCESS" BR 36$ ;; AND EXIT 35$: CLC ;; SHOW "FAILURE" 36$: MOV (SP)+,(SP)+ ;; ALIGN STACK PRESERVING C-BIT MOV (SP)+,R3 ;; RECOVER R0/R3 MOV (SP)+,R0 RETURN ;; AND RETURN TO CALLER .ENDC ;R$$MPL ; .END ;GCCI