; CL1COM - CLONE COMMUNICATIONS MODULE ; LAST EDIT: 19-NOV-81 ; .NLIST .TITLE CL1COM .LIST TTM .NLIST BEX .LIST ; ; THIS MODULE CONTAINS CL1 INTERFACES WITH THE OUTSIDE WORLD ; OUT TO PRINT A MESSAGE ON THE TERMINAL ASSOCIATED WITH ; THE CURRENT PROCESS ; INICOM TO INITIALISE MESSAGE COMMUNICATION ; ; MAP TO MAP A VAL REGION ; ; UNMAP TO UNMAP A VAL REGION (AND POSSIBLY ; RESTORE PREVIOUS EXEC MAPPING) ; ; SENDR TO SEND A REGION TO A TASK AND ATTACH IT. ; RESUMT TO RESUME A SUSPENDED TASK ; DETREG TO DETACH FROM A VAL REGION ; NEWREG TO CREATE A REGION APPROPRIATE TO THE CURRENT ; TASK STREAM. ; QMCR TO QUEUE A COMMAND LINE TO MCR ; ; .PSECT CL1COM ; .MCALL DIR$,QIO$,QIOW$,ASTX$S,SETF$S,RCVD$,SRDA$S,DSCP$S,ENCP$S .MCALL MAP$,UMAP$,RREF$,SREF$,SRRA$S,WDBBK$,CRAW$,SDAT$S .MCALL DTRG$,RDBBK$,ALTP$S,RSUM$S,MRKT$,WTSE$,CRRG$S .MCALL USTP$S,SPWN$ EOS=0 EOF=-1 CR=15 CF=12 SPACH=40 CTRLZ=32 ESCAPE=33 ; ; ; OUT - OUTPUT A STRING TO THE CURRENT PROCESS TI ; INPUT: R2=ADDRESS OF ZERO TERMINATED STRING ; ; REGISTERS DESTROYED: NONE ; ; ; OUTP- ALTERNATIVE ENTRY FOR OUT ; OUTPUT A PROMPT STRING ; ; OUTC - ALTERNATIVE ENTRY TO OUTPUT A STRING WITH NO ; LEADING LF ; ; OUT0 - TO OUTPUT A STRING WITH NO CONTROL CHARACTERS ; ; .ENABL LSB ; OUT:: CALL DISAST MOV #' ,PBLK+Q.IOPL+4 ;SET FOR CARIAGE CONTROL BR 1$ ; OUTC:: CALL DISAST MOV #'+,PBLK+Q.IOPL+4 ;SET FOR NO LINEFEED BR 1$ ; OUTP:: CALL DISAST MOV #'$,PBLK+Q.IOPL+4 ;SET FOR NO CR BR 1$ ; OUT0:: CALL DISAST TSTB (R2) ;NULL STRING ? BEQ 12$ ;IF SO DO NOTHING CLR PBLK+Q.IOPL+4 ;SET FOR NO CC ; 1$: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) CALL GTILUN ;GET CURRENT PROCESS LUN MOV R1,PBLK+Q.IOLU ;AND SAVE IN DPB MOVB R1,PBLK+Q.IOEF MOV R2,R1 ;SAVE STRING ADDRESS 2$: TSTB (R2)+ ;FIND STRING LENGTH BNE 2$ SUB R1,R2 DEC R2 BGT 3$ MOV #NULSTR,R1 INC R2 3$: MOV R1,PBLK+Q.IOPL ;SET ADDRESS IN DPB MOV R2,PBLK+Q.IOPL+2;AND STRING LENGTH DIR$ #PBLK MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 12$: RETURN .DSABL LSB ; ; ; GTILUN - GET LUN FOR CURRENT PROCESS ; ; OUTPUT: R1=LUN NUMBER ; GTILUN: MOV PROC,R1 ;GET PROCESS BEQ 1$ ;SKIP IF NONE MOV PL.LUN(R1),R1 ;GET PROCESS LUN BEQ 1$ RETURN ; 1$: MOV #1,R1 ;IF NO PROCESS USE THE CO: LUN RETURN ; ; ; ; ATTQIO - ATTACH CURRENT PROCESS TI: ; DETQIO - DETACH CURRECT PROCESS TI: ; DTQIO1 - DETACH LUN INDICATED BY R1 ; ; REGISTER R1 DESTROYED ; .ENABL LSB ; ATTQIO::MOV #IO.ATT,ADBLK+Q.IOFN BR 1$ ; DETQIO::MOV #IO.DET,ADBLK+Q.IOFN BR 1$ ; DTQIO1: MOV #IO.DET,ADBLK+Q.IOFN BR 2$ ; 1$: CALL GTILUN ;GET PROCESS TI: LUN 2$: MOV R1,ADBLK+Q.IOLU MOVB R1,ADBLK+Q.IOEF DIR$ #ADBLK RETURN ; .DSABL LSB ; ; ; .GLOBL CL1EFN ; ; PBLK: QIOW$ IO.WVB,,,,,,<0,0,0> ADBLK: QIOW$ ,,, ; NULSTR: .BYTE ' ,0 ; ; ; ; INICOM - INITIALISE MESSAGE COMMUNICATION SYSTEM ; A RECEIVE IS PERMENTLY PENDING INTO A BUFFER ALLOCATED ; HERE. ; THE RECEIVE AST ROUTINE DETERMINES TO WHICH ; PROCESS THE BUFFER IS QUEUED (USING THE TI NAME) ; AND PLACES IT IN THE ASYNCRONOUS COMMAND BUFFER QUEUE. ; INICOM::DIR$ #CRAW ;CREATE WINDOW TO MAP VAL REGIONS SRDA$S #RCVAST ;SPECIFY THE RECEIVE AST SRRA$S #REFAST ;SPECIFY RECEIVE BY REFERANCE AST CALL RCVDAT ;PICK UP ANY MESSAGES CALL RCVREG ;AND ANY REGIONS RETURN ; RCVAST: CALL RCVDAT BR ENDAST ; REFAST: CALL RCVREG ; ENDAST: ASTX$S ; ; ;+ ; RCVDAT - RECEIVE A MESSAGE FROM AN EXTERNAL TASK ; ; THERE ARE THREE TYPES OF MESSAGE WHICH WE MAY RECEIVE: ; 1) A REQUEST FROM A TASK UNDER CLONE CONTROL ; 2) A COMMAND FROM ...CL1 THE EXTERNAL COMMAND TASK ; 3) A TERMINAL INPUT COMPLETION MESSAGE FROM CL1... ; ; 1 AND 2 ARE PROCESSED LOCALY, 3 IS PROCESSED IN MODULE CL1QIO. ; ;- ; RCVDAT: MOV R0,-(SP) ;SAVE ALL REGISTERS WE USE MOV R1,-(SP) ;AS WE MAY BE IN AST STATE MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) 1$: CALL QIOFIN ;PROCESS ANY COMPLETED QIOS DIR$ #RCVD ;TRY FOR A MESSAGE FROM ANYONE ELSE BCS NORCV ;NOTHING THERE TST RBUF+4 ;IS THIS FROM THE MCR COMMAND ? BNE 2$ ;NON ZERO IF SO MOV RBUF+6,R1 ;ELSE GET TASK STREAM ADDRESS MOV RBUF,SL.TSK(R1) ;AND UPDATE TASK NAME IN CASE IT HAS CHANGED MOV RBUF+2,SL.TSK+2(R1) MOV #TS.RUN,SL.STA(R1) ;MAKE STREAM EXECUTABLE BR 3$ ;AND RETURN WAKING UP CLONE ; ; FOR MESSAGES FROM THE MCR COMMAND WE HAVE TO LOOK UP THE PROCESS BY TI: 2$: CALL GETPRC ;FIND PROCESS IN LIST OR CREATE ONE BCS 1$ ;LOSE THE MESSAGE ON ERROR MOV R0,-(SP) ;SAVE PROCESS MOV #RBUF+10,R2 ;POINT TO COMMAND TEXT CALL STRLEN ;GET COMMAND LENGTH CALL STRLIT ;ALLOCATE A BUFFER ITEM MOV R0,R1 ;COPY ITEM ADDRESS MOV (SP)+,R0 ;RESTORE PROCESS POINTER MOV R1,PL.CBF(R0) ;QUEUE BUFFER TO PROCESS ; 3$: SETF$S #CL1EFN ;SIGNAL THE EVENT TO MAIN CODE BR 1$ ;GO CHECK FOR MORE MESSAGES ; NORCV: MOV (SP)+,R4 MOV (SP)+,R3 MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; ;+ ; RCVREG - TRY TO RECEIVE A REFERANCE TO A DYNAMIC REGION ; ; WHEN A TASK CONNECTS TO CLONE IT DOES A SEND BY REFERANCE FOR ITS VALCOM ; REGION. ; ;- ; RCVREG: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV R3,-(SP) MOV R4,-(SP) 1$: CLR WDB+W.NSTS ;WINDOW STATUS SO WE PICK UP ACCESS RIGHTS DIR$ #RREF ;DO RECEIVE BY REFERANCE BCS NORCV ;NOTHING THERE MOV RBUF+10,R1 ;GET STREAM ADDRESS BEQ 2$ ;IF NULL ITS A CONNECT PACKET ; AS WE ARE ALREADY ATTACHED TO THIS REGION ; WE THROW AWAY THE NEW ATTACHMENT ; THIS BIT OF CODE IS PROBABLY NEVER EXECUTED, LET FIND OUT TRAP MOV WDB+W.NRID,RDB+R.GID DIR$ #DETBLK MOV RBUF,SL.TSK(R1) ;SAVE TASK NAME MOV RBUF+2,SL.TSK+2(R1) MOV #TS.RUN,SL.STA(R1);SET TASK ACTIVE STATE BR 3$ ; 2$: CALL GETPRC ;LOOK UP TI IN PROCESS LIST BCS 1$ ;LOSE MESSAGE ON ERROR MOV R0,R2 ;AND SAVE PROCESS ADDRESS MOV #5,R1 ;ALLOCATE CONNECT ITEM CALL GETSP MOV RBUF,4(R0) ;SAVE TASK NAME MOV RBUF+2,6(R0) MOV WDB+W.NRID,10(R0) MOV R0,PL.RBF(R2) ;QUEUE REGION TO PROCESS 3$: SETF$S #CL1EFN ;SIGNAL THE EVENT BR 1$ ;TRY FOR ANOTHER REGION ; ; ; GETPRC - LOCATE THE PROCESS NAMED IN RBUF IN THE PROCESS LIST ; IF NOT FOUND ALLOCATE A NEW PROCESS. ; ON RETURN R0=PROCESS ADDRESS ; GETPRC: MOV PROCLH,R0 ;GET FIRST PROCESS BEQ 10$ ;NOTHING THERE 1$: CMP PL.TI(R0),RBUF+4;DOES NAME MATCH BNE 2$ CMPB PL.TI+2(R0),RBUF+6;DOES UNIT MATCH BEQ 20$ ;FOUND IT 2$: MOV PL.FWD(R0),R0 ;NEXT PROCESS CMP R0,#PROCLH ;END OF LIST ? BNE 1$ ; ; NO MATCH WE HAVE TO CREATE A NEW PROCESS 10$: MOV #PL.SIZ,R1 ;ALLOCATE PROCESS ITEM CALL GETSPA BCS 21$ ;SKIP ON ALLOCATION FAIL MOV R0,R2 ;COPY NEW ITEM ADDRESS MOV #PROCLH,R3 ;GET LISTHEAD CALL LINKB ;INSERT IN LIST MOV RBUF+4,PL.TI(R0);SET TI IN ITEM MOVB RBUF+6,R1 ;GET UNIT MOV R1,PL.TI+2(R0) CLR PL.LUN(R0) ;FLAG NEW PROCESS 20$: CLC ;RETURN WITH GOOD STATUS 21$: RETURN ; ;+ ; MAP - MAP A VAL REGION ; ; THE GLOBAL MAPAPR DETERMINES THE APR USED FOR THE MAPPING ; THE ID OF THE REGION TO BE MAPPED IS OBTAINED FROM THE CURRENT STREAM ; ; INPUT: STREAM CONTEXT ; ; OUTPUT: R1 VIRTUAL ADDRESS OF MAPPED REGION ; ;- ; MAP:: CLR WDB+W.NLEN CLR WDB+W.NOFF MOV #WS.WRT,WDB+W.NSTS MOV STREAM,R1 MOV SL.REG(R1),WDB+W.NRID DIR$ #MAPB MOV W.NBAS+WDB,R1 ;RETURN BASE ADDRESS RETURN ; UNMAP:: DIR$ #UMAPB ;UNMAP FROM REGION SPECIFIED BY WDB BCC 1$ ;SKIP IF WE SUCCEDE CMP $DSW,#IE.ITS ;WINDOW NOT MAPPED ERROR ? BNE 2$ ;IF NOT WEVE GOT PROBLEMS RETURN 1$: BIT #WS.UNM,WDB+W.NSTS ;WAS UNMAP SUCCESSFUL ? BEQ 2$ ;IF NOT ERROR RETURN ; 2$: CALL ABORT ; ; SENDR - SEND A REGION TO A TASK ; SENDR:: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) MOV STREAM,R1 ;GET STREAM POINTER MOV R1,R2 ;POINT TO TASK NAME ADD #SL.TSK,R2 MOV (R2),SNDBLK+S.RETN MOV 2(R2),SNDBLK+S.RETN+2 MOV #,WDB+W.NSTS DIR$ #SNDBLK ;SEND BACK THE REGION MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; ; ; ; DETREG - DETACH CURRENT STREAM REGION ; DETREG::MOV R1,-(SP) MOV STREAM,R1 MOV SL.REG(R1),RDB+R.GID ;SET REGION ID BIS #RS.MDL,RDB+R.GSTS ;DELETE ON LAST DETACH DIR$ #DETBLK BCC 1$ MOV R2,-(SP) MOV #DETFM,R2 CALL OUT MOV (SP)+,R2 1$: MOV (SP)+,R1 RETURN ; DETFM: .ASCIZ /CLONE -- REGION DETACH FAILED/ ; ; ; ; QMCR - QUEUE A COMMAND LINE TO MCR ; INPUT: R2=STRING ADDRESS ; ; REGISTERS DESTROYED: NONE ; ; QMCR:: MOV R0,-(SP) MOV R1,-(SP) MOV R2,-(SP) CALL STRLEN ;GET STRING LENGTH IN R1 DEC R1 ;DISCOUNT ZERO BYTE MOV R2,SPWBLK+S.PWCA ;SET STRING ADDRESS MOV R1,SPWBLK+S.PWCL ;AND LENGTH MOV #MCRAST,R2 ;SET ADDRESS OF MCR COMPLETION AST CALL ALLESB ;ALLOCATE AN EXIT LINKAGE BLOCK MOV R2,SPWBLK+S.PWEA;AND STORE AST LINKAGE ADDRESS IN DPB MOV MCRNAM,SPWBLK+S.PWTN ;GET NAME OF CLI FROM CONDITIONAL MOV MCRNAM+2,SPWBLK+S.PWTN+2;ASSEMBLY IN RSXSUB DIR$ #SPWBLK ;SPAWN CLI BCC 1$ ;SKIP IF NO PROBLEMS ERROR$ $DSW ;REPORT ERROR MOV STREAM,R1 ;GET STREAM POINTER MOV SL.ESB(R1),R0 ;GET ESB ADDRESS CLR SL.ESB(R1) ;RESET ESB POINTER CALL FREESP ;DE-ALLOCATE ESB 1$: MOV (SP)+,R2 MOV (SP)+,R1 MOV (SP)+,R0 RETURN ; ; ; MCRAST - AST EXECUTED ON COMPLETION OF AN MCR REQUEST ; THE ACTUAL AST ENTRY IS LOCATED IN CLONE DYNAMIC MEMORY ; TRANSFER TO THIS POINT OCCURES WITH THE AST LINKAGE ; ITEM ADDRESS ON TOP OF THE STACK. ; MCRAST: MOV (SP)+,TEMP ;POP AST BLOCK ADDRESS MOV R0,-(SP) MOV R1,-(SP) MOV TEMP,R0 ;GET AST BLOCK ADDRESS MOV EB.STR(R0),R1 ;GET STREAM ADDRESS MOV #TS.RUN,SL.STA(R1);RESTORE STREAM TO RUN STATUS BR EXTDON ;GO DE-ALLOCATE EXIT BLOCK ; ; ; ; ; EXTAST - AST EXECUTED ON EXIT OF A CONNECTED TASK ; THE ACTUAL AST ENTRY IS LOCATED IN CLONE DYNAMIC MEMORY ; TRANSFER TO THIS POINT OCCURES WITH THE AST LINKAGE ; ITEM ADDRESS ON TOP OF THE STACK. ; EXTAST::MOV (SP)+,TEMP ;SAVE AST ENTRY ADDRESS MOV R0,-(SP) MOV R1,-(SP) MOV TEMP,R0 MOV EB.STR(R0),R1 ;GET THE ADDRESS OF THE EXITING STREAM BEQ EXTDON ;SKIP IF NULL MOV #TS.EXT,SL.STA(R1) ;FLAG STREAM EXITED CLR SL.ESB(R1) ;CLEAR EXIT BLOCK POINTER ; ; ; EXTDON: CALL FREESP ;DE-ALLOCATE STATUS BUFFER SETF$S #CL1EFN ;FLAG SOMETHING HAS HAPPENED MOV (SP)+,R1 MOV (SP)+,R0 ASTX$S ;QUIT AST ; ; ; ; TEMP: .WORD 0 RCVD: RCVD$ ,RBUF RBUF: .BLKW 15. RREF: RREF$ WDB MAPB: MAP$ WDB UMAPB: UMAP$ WDB CRAW: CRAW$ WDB SNDBLK: SREF$ ,WDB DETBLK: DTRG$ RDB MKTBLK: MRKT$ CL1EFN-1,5.,1 WTBLK: WTSE$ CL1EFN-1 SPWBLK: SPWN$ MCR...,,,,,,,,, ; VC.LEN==256. VC.L32=4 WDB:: WDBBK$ MAPAPR,VC.L32,,0,VC.L32,0,RBUF RDB:: RDBBK$ VC.L32,CL1R00,VALPAR,,0 ; .END