.TITLE STS ; PROGRAM STS PATCH TO MAKE RSX LOOK LIKE RSTS ; WRITTEN BY: FRANK PENNER ; APRIL 1981 ; modified for M-plus, July, 1983 ; this program puts patch into terminal driver ; also required is patch to module TTINI, change ; test for waiting for carrier and disabled to ; just check for disabled. .MCALL QIOW$,EXIT$S,DIR$,ALUN$ .MCALL TCBDF$,CALL,RETURN,GMCR$ .MCALL DCBDF$,F11DF$,HDRDF$,HWDDF$,PCBDF$,UCBDF$ .MCALL PKTDF$,ACNDF$ 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 ACNDF$ ;define accounting offsets BEGIN: ;BEGINNING OF PATCH CODE ; SUBROUTINE MHUPF ; MODEM HANGUP FRANK ; INPUT: ; R5 POINTER TO U.TSTA ; ; OUTPUT: ; TERMINAL STATUS AND TASK SAVED ; ; REGISTERS ALTERED: R0,R1,R2,R3,R4 U.TCI=0 ;DEFINE TT SYMS from UCBX U.TCO=14 U.TITI=40 U.TOTI=41 T$$UXL=46 U.TAST=32 U.TISV=34 U.TRTT=44 ; ENTRY: NOP ;space for XDT BPT BISB #US.CRW,U.STS-U.TSTA(R5);FIRST LINE OF TERMINAL DRIVER CODE ;restriction: ;we only save task that is attached to ;to terminal being hung up. If it is ;a spawned task, we don't bother to ;check, so saving offspring doesn't ;help if you don't save parent. ;I don't need to worry about this for ;my application. MOV U.ATT-U.TSTA(R5),R0 ;IS TERMINAL ATTACHED? BNE 10$ ;IF NE THEN ATTACHED JMP EXIT ;IF EQ NOT ATTACHED 10$: CMP T.NAM(R0),#^RWSP ;is person DT'ing? BNE 12$ ;if not equal no OK JMP EXIT ;if DT'ing forget it 12$: CMP T.NAM(R0),#^RHEL ;is person loggin in (running HEL)? BNE 120$ ;if not equal no OK JMP EXIT ;if logging in forget it 120$: MOV T.UCB(R0),R2 ;PUT TASK TI: ADD IN R2 ADD #U.TSTA,R2 ;OFFSET TO U.TSTA CMP R5,R2 ;IS ATTACHED TASK TI: THIS TERM? BEQ 11$ ;IF EQ OK SO CONTINUE JMP EXIT ;IF NOT EQ THEN NO SO EXIT 11$: 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),@#KDSAR6 ;map secpool index of ptrs MOV #140000,R3 ;set virtual address (APR 6) 1$: TST (R3)+ ;is ptr available? BEQ 2$ ;IF EQ YES CMP R3,#140000+400 ;end of index block? BLO 1$ ;if lower, no, so branch JMP EXITM ;NO SAVE UCB available, SO QUIT 2$: MOV #1,R1 ;we want 1 32 word block CALL @#$ALSEC ;allocate sec pool for save UCB BCC 31$ ;if C clear, success JMP EXITM ;if sec pool alloc fails, give up; map! 31$: MOV R0,-(R3) ;R0 has APR value to map save UCB ;put in index block to ;MARK UCB AS IN USE MOV R0,@#KDSAR5 ;map save UCB with 5 MOV R4,@#120000+24 ;save RS UCB address in save area CALL ALUCBX ;allocate a UCBX and TABUF from secpool ;destroys R1,R2 and R4, remaps APR 5 ;R0 contains APR offset for new UCBX BCC 30$ ;C set if secpool alloc fail MOV #1,R1 ;one block to deallocate (save UCB) MOV (R3),R0 ;APR offset to dealloc CALL @#$DESEC ;do it (destroys R2) CLR (R3) ;mark save UCB as not in use ;by clearing word in index block JMP EXITM ;give up trying to save this task 30$: MOV (R3),R2 ;remap from index secpool to save UCB MOV R2,@#KDSAR6 ;but I am afraid to do it in one step MOV #140000,R2 ;virt add for save UCB SUB #140000,R3 ;get byte offset to ptr ASR R3 ;make word offset MOV R3,22(R2) ;and remember for unit # MOV R5,R3 ;PUT U.TSTA PTR ALSO IN R3 ADD #U.ATT-U.TSTA,R3 ;POINT TO ATTACH WORD ADD #4,R2 ;skip over first 2 words MOV U.LUIC-U.TSTA(R5),(R2)+ ;SAVE LOGIN UIC MOV (R3),(R2)+ ;SAVE ATTACH CONTENTS MTPS #240 ;lock out interrupts ;;;the following is too sleazy not to MOVB U.STS-U.TSTA(R5),@#140000 ;;;MOVE STATUS WORD U.STS BISB #US.OIU,U.STS-U.TSTA(R5) ;;;SET OUTPUT INTER UNEXP IN OLD UCB CLR (R3)+ ;;;UNATTACH FROM OLD MOV (R3),(R2)+ ;;;save U.TAPR value MOV R0,(R3)+ ;;;set new UCBX address MOV (R3),(R2)+ ;;;MOVE FIRST STATUS WORD U.TSTA CLR (R3)+ ;;;clear first status word IN OLD MOV (R3),(R2)+ ;;;MOVE SECOND STATUS WORD U.TSTA BIC #^C,(R3)+ ;;;CLR ALL BUT TERM CHAR IN OLD MOV (R3)+,(R2)+ ;;;MOVE THIRD STATUS WORD U.TSTA MOVB U.TFRQ-U.TSTA(R5),@#140000+1;;;save fork request byte BEQ 15$ ;;;if 0 then no need to deque fork CLRB U.TFRQ-U.TSTA(R5) ;;;clear it ; ; MOV @#$TTUQ,R4 ;;;point to UCB que head ; 15$: MTPS #0 ;;;re-enable interrupts MOV @#140000+10,@#KDSAR5 ;use saved UCBX to map old UCBX MOV #120000,R3 ;SET VIRTUAL ADDRESS OF UCBX MOV U.TCI(R3),R1 ;POINT R1 TO I/O PACKET BEQ 9$ ;IF ZERO THEN INPUT not BUSY BIT #S1.USI,@#140000+12 ;was unsolicited input set? BEQ 3$ ;if equal no, so do I/O PKT save 9$: MOV U.TCO(R3),R1 ;POINT R1 TO I/O PACKET BNE 3$ ;IF NON-ZERO THEN OUTPUT NOT BUSY CLR (R2)+ ;CLEAR SAVE I/O PACKET ADDRESS BR 4$ ;SKIP I/O PACKET SAVE 3$: MOV @#140000+24,I.UCB(R1) ;PUT NEW UCB ADDRESS IN I/O PACKET MOV R1,(R2)+ ;SAVE I/O PACKET ADDRESS ;restriction: ;should also scan SCB list head ;for other I/O packets for this unit ;from this task, since my applications ;don't do multiple I/O's to the ;terminal I won't worry about it. 4$: MOVB U.TBSZ-U.TSTA(R5),@#140000+26 ;save type ahead buffer size MOV U.CW2-U.TSTA(R5),@#140000+30 ;save U.CW2 BIC #U2.DH1!U2.DJ1!U2.RMT!U2.LOG!U2.DZ1!U2.PRV,@#140000+30 ;don't save these bits MOV U.UIC-U.TSTA(R5),@#140000+66 ;save default UIC BIC #UM.CMD,U.MUP-U.TSTA(R5);clear command in progress bit MOV @#140000+6,R0 ;repoint R0 to TCB, use saved att word MOV @#140000+24,T.UCB(R0) ;PUT NEW UCB ADDRESS IN ATT TASK TCB TI BIS #TS.STP,T.STAT(R0) ;STOP TASK ; ;begin task rename ;begin case of TT## MOV R5,R3 ;put U.TSTA address in R3 SUB #U.TSTA,R3 ;make into UCB address MOV U.DCB(R3),R1 ;R3 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 R2,R3 ;ADD LOWEST UNIT # TO DEV UNIT # MOV R3,@#140000+2 ;PUT TERMINAL NUMBER INTO SAVE UCB 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 EXITR ;IF EQ NOT SET SO QUIT 60$: MOV R3,R1 ;SAVE UNIT NUMBER IN R1 MOV R3,R2 ;SAVE UNIT NUMBER IN R2 ALSO ASH #-3,R2 ;DIV UNIT # BY 8 BEQ 20$ ;IF ZERO USE OTHER CODE CMP #7,R2 ;is number greater than 77? BGT 23$ ;if greater than no, so not A,B,etc. ADD #^RTT-7,R2 ;add to rad50 TT to get TTA, etc. BR 24$ ;skip other case 23$: ADD #^RTT0,R2 ;ADD TO RAD50 TT TO GET TT# 24$: CMP R2,T.NAM(R0) ;COMPARE TO TASK NAME BNE 5$ ;TASK NAME NOT TT# 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$: MOVB @#140000+22,R2 ;PUT SAVE RT DEVICE NUMBER IN R2 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 #^RRT-7,R2 ;add to rad50 RT to get RTA, etc. BR 26$ ;skip other case 25$: ADD #^RRT0,R2 ;ADD RAD50 RT0 TO GET RT# 26$: MOV R2,T.NAM(R0) ;CHANGE 1ST HALF OF NAME TO RT# MOVB @#140000+22,R1 ;PUT SAVE RT DEVICE NUMBER IN R1 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 EXITR ;ALL DONE SO EXIT 20$: BIC #177770,R1 ;MASK OFF ALL BUT LSD OF UNIT # ADD #^RTT0,R1 ;ADD TO RAD50 TT TO GET TT# CMP R1,T.NAM(R0) ;COMPARE TO TASK NAME BNE 5$ ;TASK NAME NOT TT# 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$: MOVB @#140000+22,R1 ;PUT SAVE RT DEVICE NUMBER IN R1 BIC #177770,R1 ;MASK OFF ALL BUT LSD OF UNIT # ADD #^RRT0,R1 ;ADD RAD50 RT0 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 EXITR ;ALL DONE SO EXIT ;end of TT## case ;begin XXXT## case 5$: MOV R3,R1 ;SAVE UNIT NUMBER AGAIN IN R1 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 #^RT+36,R3 ;ADD T PLUS 36 FOR RAD50 OFFSET CMP R3,T.NAM+2(R0) ;DOES TASK END WITH T##? BNE EXITR ;NO SO QUIT 6$: MOVB @#140000+22,R3 ;PUT SAVE RT DEVICE NUMBER IN R3 MOV R3,R1 ;also in R1 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 #^RR+36,R3 ;ADD R PLUS 36 FOR RAD50 OFFSET MOV R3,T.NAM+2(R0) ;CHANGE NAME TO XXXR## BR EXITR ;ALL DONE 7$: ADD #36,R1 ;CONVERT TO RAD50 MUL #50,R1 ;SHIFT TO MIDDLE DIGIT ADD #^RT,R1 ;ADD RAD50 T CMP R1,T.NAM+2(R0) ;DOES TASK END WITH T#? BNE EXITR ;NO SO QUIT BR 6$ ;GO TO RENAME CODE 8$: MOVB @#140000+22,R1 ;PUT SAVE UCB UNIT NUMBER IN R1 ADD #36,R1 ;CONVERT TO RAD50 MUL #50,R1 ;SHIFT TO MIDDLE DIGIT ADD #^RR,R1 ;ADD RAD50 R MOV R1,T.NAM+2(R0) ;DOES TASK END WITH T#? EXITR: ;end of task rename ;save three more things ;at this time 6 is mapped to save UCB MOV #140000+32,R3 ;point to save UCB, save name field MOV U.UAB-U.TSTA(R5),@#KDSAR5 ;map UAB with APR 5 BEQ 3$ ;if zero, no accounting CMPB #BT.UAB,@#120000+B.TYP ;check to make sure UAB BNE 3$ ;if not, quit MOV #120000+B.NAM,R2 ;point to UAB name field MOV #8.,R4 ;8 words, 16 bytes 1$: MOV (R2)+,(R3)+ ;move it word at a time SOB R4,1$ ;all 8 MOV #120000+B.BEG,R2 ;point to UAB login time field MOV #3.,R4 ;3 words, 6 bytes 2$: MOV (R2)+,(R3)+ ;move it word at a time SOB R4,2$ ;all 3 BR 5$ ;all done 3$: MOV #8.+3,R4 ;name + login time 4$: CLR (R3)+ ;null it out SOB R4,4$ ;all 8 5$: MOV #$TTNS-14,R2 ;POINT TO CURRENT TIME 10$: MOVB (R2)+,(R3)+ ;COPY FIELD INC R2 ;SKIP HIGH BYTE OF WORD FIELD IN SYSCM CMP #$TTNS,R2 ;COPYING COMPLETE? BHI 10$ ;IF HI NO EXITM: MOV @#$DALED,@#KDSAR6 ;restore mapping EXIT: JMP @#MHUP+6 ;GO BACK TO TERMINAL DRIVER ;this code was stolen from TTTBL.MAC and the code rearranged so I ;can elevate IPL for as few instructions as necessary. .ENABL LSB ; ;+ ; ; ALUCBX - ALLOCATE A UCB EXTENSION (UCBX) AND TYPEAHEAD BUFFER (TABUF) ; STUCBX - SET UP A UCB EXTENSION AND TYPEAHEAD BUFFER ; ; INPUT: ; R0 APR BIAS OF 1ST SECONDARY POOL BLOCK (IF ENTRY AT STUCBX) ; R5 POINTER TO U.TSTA ; ; OUTPUT: ; IF SUCCESS: ; CC-C 0 ; UCBX AND CONTIGUOUS TABUF ALLOCATED FROM SECONDARY POOL AND INITIALIZED ; ; IF FAILURE: ; CC-C 1 ; IE.ALC RETURNED IN $SCERR TO INDICATE FAILURE TO BRING TERMINAL ONLINE ; ;- ; ALUCBX: CALL 20$ ;GET NUMBER OF SECONDARY POOL NODES REQUIRED CALL @#$ALSEC ;ALLOCATE THEM FOR USE BY THIS TERMINAL BCS 10$ ;BRANCH ON ALLOCATION FAILURE ;STUCBX:: ; the folowing instruction is the one instruction that was screwing me up ; I want to change to the new UCBX with interrupts disabled ; MOV R0,U.TAPR-U.TSTA(R5) ;THESE NODES BECOME THE UCBX AND TABUF MOV R0,@#KDSAR5 ;MAP THE UCBX AND TABUF MOV #120000,R4 ;SET THEIR VIRTUAL ADDRESS ASSUME U.TCI,0 CLR @R4 ;NO CURRENT INPUT REQUEST CLR U.TCO(R4) ;NO CURRENT OUTPUT REQUEST CLR U.TAST(R4) ;NO AST BLOCK CLRB U.TISV(R4) ;INITIALIZE STATE VARIABLE ASSUME U.TITI&1,0 ASSUME U.TOTI,U.TITI+1 CLR U.TITI(R4) ;CLEAR INPUT AND OUTPUT TIMERS CLR U.TRTT(R4) ;NO TERMINATOR TABLE ADD #U.TTBF,R4 ;POINT TO TYPEAHEAD BUFFER CLR (R4)+ ;INITIALIZE HEADER CLRB (R4)+ ;RESET ACTIVE COUNT AND CLEAR CARRY MOVB U.TBSZ-U.TSTA(R5),(R4) ;SET SIZE OF TABUF RETURN 10$: MOVB #IE.ALC,$SCERR ;INDICATE CAUSE OF FAILURE RETURN ;RETURN WITH CARRY SET ; ; CALCULATE THE NUMBER OF SECONDARY POOL BLOCKS REQUIRED TO CONTAIN THE ; UCB EXTENSION AND A TYPEAHEAD BUFFER WHOSE SIZE IS KEPT IN OFFSET U.TBSZ ; 20$: CLR R1 ;PREVENT UNWANTED SIGN EXTEND BISB U.TBSZ-U.TSTA(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 RETURN ;RETURN WITH RESULT IN R1 .DSABL LSB END: SAVEM1: .BLKW 1 ;space to save apr 1 SAVEM2: .BLKW 1 ;and 2 START: ;SEARCH PARTITION LIST FOR DRVPAR MOV $PARHD,R0 ;POINT TO FIRST PCB IN LIST 10$: CMP P.NAM(R0),#^RDRV ;FIRST HALF OF NAME MATCH ? BNE 20$ ;IF NE NO CMP P.NAM+2(R0),#^RPAR ;SECOND HALF OF NAME MATCH ? BEQ 30$ ;IF EQUALS YES 20$: MOV P.LNK(R0),R0 ;GET LINK TO NEXT PCB TST R0 ;NULL LINK? BNE 10$ ;IF NOT EQUALS NO BR THEEND ;CAN'T FIND DRVPAR SO GIVE UP 30$: ;FOUND IT MOV P.SUB(R0),R0 ;POINT TO NEXT SUBPARTITION TST R0 ;NULL LINK? BEQ THEEND ;YES, GIVE UP BIT #PS.COM,P.STAT(R0) ;common PCB? BEQ 30$ ;NO MATCH, GET NEXT SUB PARTITION CMP P.ST2(R0),#P2.DRV ;driver? BNE 30$ ;NO MATCH, GET NEXT SUB PAR MOV P.OWN(R0),R3 ;put address of DCB in R3 CMP #"TT,D.NAM(R3) ;DCB for TT:? BNE 30$ ;no, next please ; ITS A MATCH! MOV P.REL(R0),R5 ;PUT PHYSICAL ADDRES OF TT: IN R5 MOV #END-BEGIN,R1 ;SIZE OF BLOCK NEEDED FROM POOL ASR R1 ;CONVERT BYTES TO WORDS MOV #BEGIN,R2 ;PUT ADDRESS OF STUFF TO BE MOVED IN R2 MOVB #1,$CXDBL ;;disable context switching MOV @#UISAR1,SAVEM1 ;;save user data APR 1 MOV @#UISAR2,SAVEM2 ;;save user data APR 2 MOV R5,@#UISAR1 ;;remap to TT: driver ADD #200,R5 ;;next APR MOV R5,@#UISAR2 ;; MOV #43400,R0 ;;point to end of term driver code (APR 1 & 2) 1$: MOV (R2)+,(R0)+ ;;MOV IT WORD AT A TIME SOB R1,1$ ;;DO ALL WORDS IN DEVICE DCB AND UCB MOV #137,@#MHUP-100000 ;;patch in JMP @# MOV #143400,@#MHUP-100000+2 ;;to newly copied code MOV #240,@#MHUP-100000+4 ;;nop MOV SAVEM1,@#UISAR1 ;;restore user data APR 1 MOV SAVEM2,@#UISAR2 ;;restore user data APR 2 CLRB $CXDBL ;;enable context switching THEEND: EXIT$S .END START