.TITLE ATT ; PROGRAM ATT PATCH TO MAKE RSX LOOK LIKE RSTS ; WRITTEN BY: FRANK PENNER ; APRIL 1981 ; modified for M+, July 1983 ; THIS PROGRAM WILL 'ATTACH' A TERMINAL TO 'DETACHED' TASK ; SEE PROGRAM STS .MCALL QIOW$,EXIT$S,DIR$,ALUN$,MRKT$S,WTSE$S .MCALL TCBDF$,CALL,RETURN,GMCR$ .MCALL DCBDF$,F11DF$,HDRDF$,HWDDF$,PCBDF$,UCBDF$ .MCALL PKTDF$ TCBDF$ ;DEFINE TCB OFFSETS DCBDF$ ;DEFINE DCB OFFSETS HDRDF$ ;DEFINE TASK HEADER OFFSETS HWDDF$ ;DEFINE HARDWARE OFFSETS PCBDF$ ;DEFINE PCB OFFSETS UCBDF$ ,,TTDEF ;DEFINE UCB OFFSETS PKTDF$ ;DEFINE I/O PACKET OFFSETS T$$UXL=46 ERRFLG: .WORD 0 ;error flag IOST: .BLKW 2 ;I/O STATUS BLOCK ATTDPB: QIOW$ IO.ATT,TLUN,TEFL,,IOST QIHDPB: QIOW$ IO.WLB,TLUN,TEFL,,IOST,, QIODPB: QIOW$ IO.WLB,TLUN,TEFL,,IOST,, QIBDPB: QIOW$ IO.WBT,TLUN,TEFL,,IOST,, TLUN= 5 TEFL= 2 VFC= 40 OUTBUF: .BLKB 132. OUTBUS=.-OUTBUF HEDBUF: .ASCII /Job Term Login Disconnect/<15><12> .ASCII /No. No. UIC Task Username Time Time/ HEDBUS=.-HEDBUF OBTBUF: .ASCII /Type GOLD-Menu and a carriage return to continue./ OBTBUS=.-OBTBUF PICBUF: .ASCII /Job number not detached under this account./ PICBUS=.-PICBUF ISTRNG: .ASCII /%21<%11<%4<%O%4>TT%O:%11>[%O,%O]%21>%2R %A. / .ASCIZ /%14A %Y %2Z %Y %2Z/ .EVEN ARGBLK: .BLKW 6 .WORD NAMES+14. .WORD NAMES DATES: .BLKW 10. NAMES: .BLKB 16. QIORPR: QIOW$ IO.RPR,TLUN,TEFL,,IOST,, PVFC= 44 TMO= 5 INBUF: .BLKB 132. INBUS=.-INBUF PRBUF: .ASCII <15><12>/Job number to attach to: / PRBUS=.-PRBUF .EVEN FLAG: .WORD 0 ;FLAG WORD FOR DETACHED TASKS PRESENT START: MOV $TKTCB,R3 ;PUT OUR TCB ADDRESS IN R3 MOV T.UCB(R3),R3 ;PUT OUR TI: UCB ADD IN R3 TST U.ATT(R3) ;is our terminal attached? BNE 70$ ;if not equal attached so quit DIR$ #ATTDPB ;attach terminal BCC 3$ ;if C clear OK 70$: JMP EXIT ;if can't attach give up 3$: CMPB #IS.SUC,IOST ;check attach status BNE 70$ ;if not equal not success, so quit MOV @#$DEVHD,R4 ;PUT FIRST DCB ADDRESS IN R4 13$: CMP #"RS,D.NAM(R4) ;RS device? BEQ 14$ ;if equal ,yes MOV D.LNK(R4),R4 ;point to next DCB BNE 13$ ;last DCB in chain? if not equal no JMP EXIT ;RS DCB not found so quit 14$: MOV D.UCB(R4),R4 ;POINT TO FIRST UCB FOR RS: DEV MOV U.CW2(R4),R5 ;get APR value for mapping MOV #140000,R4 ;set virtual address (APR 6) MOVB #1,$CXDBL ;disable context switching MOV R5,@#UDSAR6 ;map secpool index of ptrs MOV @#UDSDR5,@#UDSDR6 ;make 6 look like 5 1$: MOV (R4)+,R1 ;this saved UCB in use? BEQ 2$ ;IF EQ no MOV R1,@#UDSAR6 ;map secpool saved info BIT #U2.PRV,U.CW2(R3) ;is terminal privileged? BNE 71$ ;if not equal yes, so display all CMP @#140000+4,U.LUIC(R3) ;IS SAVED UIC SAME AS TERM UIC? BNE 72$ ;if no skip 71$: INC FLAG ;SET FLAG TO INDICATE RS TASKS PRESENT MOV #ARGBLK,R2 ;PUT ADDRESS OF ARGBLK INTO R2 MOVB @#140000+22,(R2)+ ;PUT RSTS UNIT NUMBER IN ARGBLK CLRB (R2)+ ;CLEAR TOP BYTE MOV @#140000+2,(R2)+ ;PUT OLD TERMINAL NUMBER IN ARGBLK MOVB @#140000+5,(R2)+ ;PUT HALF OF TERM UIC IN ARGBLK CLRB (R2)+ ;CLEAR TOP BYTE MOVB @#140000+4,(R2)+ ;PUT HALF OF TERM UIC IN ARGBLK CLRB (R2)+ ;CLEAR TOP BYTE MOV @#140000+6,R0 ;PUT ADDRESS OF TASK IN R0 MOV T.NAM(R0),(R2)+ ;PUT 1ST HALF OF TASK NAME IN ARGBLK MOV T.NAM+2(R0),(R2)+ ;PUT 2ND HALF OF TASK NAME IN ARGBLK MOV #8.,R0 ;8. words MOV #140000+32,R1 ;saved name field MOV #NAMES,R2 ;place to put name 74$: MOV (R1)+,(R2)+ ;one word at a time SOB R0,74$ ;do all 8. words MOV #DATES,R2 ;point R2 at date/time part of ARGBLK MOV #5.,R0 ;date/time each 6 byte/word 75$: MOVB (R1)+,(R2)+ ;move byte at a time from saved date CLRB (R2)+ ;skip over byte; expand byte to word SOB R0,75$ ;do it all INC R1 ;skip over seconds byte MOV #5.,R0 ;date/time each 6 byte/word 76$: MOVB (R1)+,(R2)+ ;move byte at a time from saved date CLRB (R2)+ ;skip over byte; expand byte to word SOB R0,76$ ;do it all CLRB $CXDBL ;re enable context switching CMP FLAG,#1 ;first time to output line? BNE 77$ ;if not equal no, so branch DIR$ #QIHDPB ;output heading 77$: MOV #OUTBUF,R0 ;PUT ADDRESS OF OUTPUT BUFFER IN R0 MOV #ISTRNG,R1 ;PUT ADDRESS OF INPUT STRING IN R1 MOV #ARGBLK,R2 ;PUT ADDDRES OF ARGBLK IN R2 CALL $EDMSG ;CALL EDIT MESSAGE ROUTINE MOV R1,QIODPB+Q.IOPL+2 ;PUT SIZE OF MESSAGE IN DPB DIR$ #QIODPB ;PRINT OUT ON TERMINAL MOVB #1,$CXDBL ;disable context switching MOV @#UDSDR5,@#UDSDR6 ;make 6 look like 5 72$: MOV R5,@#UDSAR6 ;map secpool index of ptrs 2$: CMP R4,#140000+400 ;end of index block? BLO 1$ ;if lower, no, so branch CLRB $CXDBL ;re enable context switching TST FLAG ;ANY DETACHED TASKS? BNE 10$ ;DETACHED TASKS JMP EXIT ;NO DETACHED TASKS 10$: DIR$ #QIORPR ;ASK FOR NUMBER TO ATTACH TO TST IOST+2 ;HOW MANY BYTES TYPED? BNE 11$ ;IF SOME KEEP GOING JMP EXITPI ;NO BYTES TYPED 11$: MOV #INBUF,R0 ;PUT ADDRESS OF TYPE STUFF IN R0 CALL $COTB ;CALL OCTAL TO BINARY CONVERSION ;wipes R0,R1,R2 TST R2 ;is terminating character a null?? BEQ 73$ ;if yes OK JMP EXITPI ;if not quit 73$: ASL R1 ;R1 has number, make byte offset ADD #140000,R1 ;use APR 6 to map index block CALL $SWSTK,200$ ;SWITCH TO SYSTEM STATE MOV R5,@#KDSAR6 ;;map secpool index of ptrs MOV (R1),R4 ;;this pointer in use? BNE 12$ ;;YES SO OK JMP 99$ ;;NOT IN USE IF EQ SO QUIT with err 12$: CLR (R1) ;;MARK SAVE UCB AS NOT IN USE MOV R4,@#KDSAR6 ;;map save area CMP @#140000+4,U.LUIC(R3) ;;IS SAVED UIC SAME AS TERM UIC? BEQ 40$ ;;YES SO OK MOV R5,@#KDSAR6 ;;map secpool index of ptrs MOV R4,(R1) ;;restore zeroed pointer in index block JMP 99$ ;;NO SO QUIT with err 40$: MOV R3,R5 ;;PUT UCB PTR ALSO IN R5 BISB #US.CRW,U.STS(R5) ;;set wait for carrier to disable ;;processing of input interrupts MOV #140000,R2 ;;PUT SAVE UCB PTR ALSO IN R2 ADD #U.ATT,R3 ;;POINT TO ATTACH WORD ADD #6,R2 ;;POINT TO SAVE AREA PAST UIC MOV (R2)+,R0 ;;PUT ADDRESS OF TASK IN R0 MOV R0,(R3)+ ;;SAVE ATTACH CONTENTS MOV (R3),R4 ;;save old U.TAPR in R4 MOV (R2)+,(R3)+ ;;MOVE UCBX ADDRESS U.TAPR MOV (R2)+,(R3)+ ;;MOVE FIRST STATUS WORD U.TSTA MOV (R2)+,(R3)+ ;;MOVE SECOND STATUS WORD U.TSTA MOV (R2)+,(R3)+ ;;MOVE THIRD STATUS WORD U.TSTA MOV (R2),R1 ;;POINT R1 TO I/O PACKET BEQ 16$ ;;SKIP I/O PACKET SAVE 15$: MOV R5,I.UCB(R1) ;;PUT NEW UCB ADDRESS IN I/O PACKET 16$: MOV R5,T.UCB(R0) ;;PUT NEW UCB ADDRESS IN ATT TASK TCB BIC #^C,U.CW2(R5) ;;don't clear saved bits BIS @#140000+30,U.CW2(R5) ;;move some saved bits to UCB MOV @#140000+66,U.UIC(R5) ;;blat default UIC BITB #US.OIU,@#140000 ;;IS OUTPUT INTERRUPT UNEXPECTED BNE 4$ ;;IF NOT EQ YES BICB #US.OIU,U.STS(R5) ;;CLEAR OUTPUT INTER UNEXP IN OLD UCB ;;on a DH, must setup registers ;;I don't 4$: BIC #TS.STP,T.STAT(R0) ;;UNSTOP TASK BICB #US.CRW,U.STS(R5) ;;clear wait for carrier to re-enable ;;processing of input interrupts ;;deall secpool MOV R0,R3 ;;put TCB address in R3 MOV R4,R0 ;;R4 has APR value of UCBX to dealloc CLR R1 ;PREVENT UNWANTED SIGN EXTEND BISB U.TBSZ(R5),R1 ;GET THE SIZE OF THE TABUF LESS ITS HEADER ADD #T$$UXL+4+77,R1 ;INCLUDE TABUF HEADER, UCBX, AND ROUND UP ASH #-6,R1 ;CONVERT TO NUMBER OF SEC POOL BLOCKS REQUIRED CALL $DESEC ;DEALLOCATE THE UCBX AND TABUF ;clobbers R0,R1,R2 MOVB @#140000+26,U.TBSZ(R5) ;;restore typahd size from save to UCB ;;must be done after above deallocate TSTB @#140000+1 ;check fork request que byte BEQ 61$ ;if equal then no need to que fork blk MTPS #240 ;disable interupts ;;;start of code stolen from TTCIS ;;;easier to steal than map and call ;;;stolen from end MOV #$TTUQ+2,R4 ;;;POINT TO POINTER TO LAST IN QUEUE BIS #S1.DSI,U.TSTA(R5);;;FORCE INPUT TO TABUF ;;;PREVENT RETRIEVAL FROM TABUF MOV R5,R2 ;;;put UCB add in R2 ADD #U.TFLK,R2 ;;;POINT TO U.TFLK MOVB @#140000+1,U.TFRQ(R5) ;;;restore fork request que byte MOV R2,@(R4)+ ;;;N - QUEUE IT MOV R2,-(R4) ;;;SET NEW LAST CLR @R2 ;;;CLEAR LINK WORD ;;;stolen from beginning MOV #$TTFB+2,R4 ;;;POINT TO PC IN FORK BLOCK TST (R4)+ ;;;FORK BLOCK ALREADY IN QUEUE? BNE 62$ ;;;Y - RETURN MOV #62$,-(SP) ;;;push our return address MOV #FP000,-(SP) ;;;push terminal driver fork PC address JMP $FORK0 ;;;QUEUE FORK BLOCK ;;;end of code stolen from TTCIS 62$: MTPS #0 ;re-enable interupts 61$: MOV @#140000+22,R4 ;;put RS unit number in R4 MOV @#KDSAR6,R0 ;;put APR offset of save UCB in R0 MOV #1,R1 ;;save UCB is one block long CALL $DESEC ;;deallocate it from secondary pool ;;clobbers R0,R1,R2 ;;somewhere here the UCBX should be ;;checked for an AST block, if there ;;is an AST block, the UCBX pointer ;;in it should be changed ;; ;;BEGIN TASK RENAME ;;beginning of RT## case MOV R3,R0 ;;put TCB address back into R0 BIT #T3.REM,T.ST3(R0) ;;CHECK REM ON EXIT FLAG IN TASK TCB BNE 60$ ;;if not equal set so go for it JMP 100$ ;;IF EQ NOT SET SO QUIT 60$: MOV R5,R3 ;put UCB address in R3 MOV U.DCB(R3),R1 ;R1 NOW POINTS TO DCB SUB D.UCB(R1),R3 ;SUBTRACT 1ST UCB ADDRESS FROM MINE CLR R2 ;CLEAR R2 FOR HIGH WORD FOR DIV DIV D.UCBL(R1),R2 ;DIVIDE UCB DIFFERENCE BY UCB LENGTH MOVB D.UNIT(R1),R3 ;PUT LOWEST UNIT # IN R3 ADD R3,R2 ;ADD LOWEST UNIT # TO DEV UNIT # MOVB R4,R3 ;;PUT SAVE RS DEVICE NUMBER IN R3 MOV R3,R1 ;;PUT IN R1 ALSO ASH #-3,R3 ;;DIV UNIT # BY 8 BEQ 20$ ;;IF ZERO USE OTHER CODE CMP #7,R3 ;;is number greater than 77? BGT 23$ ;;if greater than no, so not A,B,etc. ADD #^RRT-7,R3 ;;add to rad50 RT to get RTA, etc. BR 24$ ;;skip other case 23$: ADD #^RRT0,R3 ;;ADD TO RAD50 RT TO GET RT# 24$: CMP R3,T.NAM(R0) ;;COMPARE TO TASK NAME BNE 5$ ;;TASK NAME NOT RT# SO TRY NEXT TEST BIC #177770,R1 ;;MASK OFF ALL BUT LSD OF UNIT # ADD #36,R1 ;;CONVERT TO RAD50 MUL #50*50,R1 ;;MOVE TO FIRST DIGIT CMP R1,T.NAM+2(R0) ;;IS LAST HALF OF TASK NAME JUST #? BNE 5$ ;;NO SO TRY NEXT TEST 21$: MOV R2,R1 ;;PUT NEW TERM DEVICE NUMBER IN R1 ASH #-3,R2 ;;DIV BY 8 TO GET 2ND DIGIT OF UNIT NUM BEQ 22$ ;;IF EQUAL GO TO SINGLE DIGIT CODE CMP #7,R2 ;;is number greater than 77? BGT 25$ ;;if greater than no, so not A,B,etc. ADD #^RTT-7,R2 ;;add to rad50 TT to get TTA, etc. BR 26$ ;;skip other case 25$: ADD #^RTT0,R2 ;;ADD RAD50 TT0 TO GET TT# 26$: MOV R2,T.NAM(R0) ;;CHANGE 1ST HALF OF NAME TO RT# BIC #177770,R1 ;;MASK OFF ALL BUT LSD OF UNIT # ADD #36,R1 ;;CONVERT TO RAD50 MUL #50*50,R1 ;;MOVE TO FIRST DIGIT MOV R1,T.NAM+2(R0) ;;CHANGE LAST HALF OF NAME TO RT## BR 100$ ;;ALL DONE SO EXIT 20$: BIC #177770,R1 ;;MASK OFF ALL BUT LSD OF UNIT # ADD #^RRT0,R1 ;;ADD TO RAD50 RT TO GET TT# CMP R1,T.NAM(R0) ;;COMPARE TO TASK NAME BNE 5$ ;;TASK NAME NOT RT# SO TRY NEXT TEST TST T.NAM+2(R0) ;;IS LAST HALF OF TASK NAME NULL? BNE 5$ ;;NO SO TRY NEXT TEST BR 21$ ;;GO TO CHANGE NAME CODE 22$: BIC #177770,R1 ;;MASK OFF ALL BUT LSD OF UNIT # ADD #^RTT0,R1 ;;ADD RAD50 TT0 TO GET TT# MOV R1,T.NAM(R0) ;;CHANGE 1ST HALF OF NAME TO RT# CLR T.NAM+2(R0) ;;CHANGE LAST HALF OF NAME TO NULL BR 100$ ;;ALL DONE SO EXIT ;;end of RT## case ;;beginning of XXXR## case 5$: MOVB R4,R1 ;;SAVE UNIT NUMBER AGAIN IN R1 MOV R1,R3 ;;PUT UNIT NUMBER IN R3 ALSO ASH #-3,R3 ;;GET TOP DIGIT OF UNIT NUMBER BEQ 7$ ;;IF EQUAL THEN SKIP INCLUDING A ZERO CMP #7,R3 ;;is number greater than 77? BGT 50$ ;;if greater than no, so not A,B,etc. SUB #7,R3 ;;subtract 7 to get RAD50 XXXA, etc. BR 51$ ;;skip other case 50$: ADD #36,R3 ;;CONVERT TO RAD50 51$: MUL #50,R3 ;;SHIFT TO MIDDLE DIGIT BIC #177770,R1 ;;MASK OFF ALL BUT LSD OF UNIT NUMBER ADD R1,R3 ;;PUT DIGITS TOGETHER ADD #^RR+36,R3 ;;ADD T PLUS 36 FOR RAD50 OFFSET CMP R3,T.NAM+2(R0) ;;DOES TASK END WITH R##? BNE 100$ ;;NO SO QUIT 6$: MOV R2,R3 ;;PUT NEW TERM DEVICE NUMBER IN R3 MOV R3,R1 ;;IN R1 ALSO ASH #-3,R3 ;;GET TOP DIGIT OF UNIT NUMBER BEQ 8$ ;;IF EQUAL THEN SKIP INCLUDING A ZERO CMP #7,R3 ;;is number greater than 77? BGT 52$ ;;if greater than no, so not A,B,etc. SUB #7,R3 ;;subtract 7 to get RAD50 XXXA, etc. BR 53$ ;;skip other case 52$: ADD #36,R3 ;;CONVERT TO RAD50 53$: MUL #50,R3 ;;SHIFT TO MIDDLE DIGIT BIC #177770,R1 ;;MASK OFF ALL BUT LSD OF UNIT NUMBER ADD R1,R3 ;;PUT DIGITS TOGETHER ADD #^RT+36,R3 ;;ADD R PLUS 36 FOR RAD50 OFFSET MOV R3,T.NAM+2(R0) ;;CHANGE NAME TO XXXR## BR 100$ ;;ALL DONE 7$: ADD #36,R1 ;;CONVERT TO RAD50 MUL #50,R1 ;;SHIFT TO MIDDLE DIGIT ADD #^RR,R1 ;;ADD RAD50 R CMP R1,T.NAM+2(R0) ;;DOES TASK END WITH R#? BNE 100$ ;;NO SO QUIT BR 6$ ;;GO TO RENAME CODE 8$: ADD #36,R1 ;;CONVERT TO RAD50 MUL #50,R1 ;;SHIFT TO MIDDLE DIGIT ADD #^RT,R1 ;;ADD RAD50 T MOV R1,T.NAM+2(R0) ;;DOES TASK END WITH T#? BR 100$ ;;all done so quit 99$: MOV #1,ERRFLG ;;signal error 100$: RETURN ;;RETURN TO USER STATE 200$: ;come here after switch stack TST ERRFLG ;error signaled? BNE EXITPI ;if not equal yes, so branch DIR$ #QIBDPB ;do break thru write of attach message BR EXIT ;also resumes output if output interupt ;expected, ;this is all that is needed for a DZ ;resuming output in progress is much ;harder on a DH, since the DH registers ;must be set up EXITPI: MOV #PICBUF,QIODPB+Q.IOPL ;put picky,picky, text address in DPB MOV #PICBUS,QIODPB+Q.IOPL+2 ;also size of picky, picky text DIR$ #QIODPB ;print it out EXIT: EXIT$S .END START