.NLIST ; COPYRIGHT (C) 1975 ; ; DIGITAL EQUIPMENT CORPORATION ; MAYNARD, MASSACHUSETTS 01754 ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE FOR USE ONLY ; ON A SINGLE COMPUTER SYSTEM AND MAY BE COPIED ONLY WITH ; THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS ; SOFTWARE, OR ANY OTHER COPIES THEREOF, MAY NOT BE PROVIDED ; OR OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON EXCEPT ; FOR USE ON SUCH SYSTEM AND TO ONE WHO AGREES TO THESE ; LICENSE TERMS. TITLE TO AND OWNERSHIP OF THE SOFTWARE ; SHALL AT ALL TIMES REMAIN IN DIGITAL. ; ; THE INFORMATION IN THIS DOCUMENT IS SUBJECT TO ; CHANGE WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED ; AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. ; DIGITAL ASSUMES NO RESPONSIBILITY FOR ANY ERRORS THAT ; MAY APPEAR IN THIS DOCUMENT ; ; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE ; OR RELIABILITY OF ITS SOFTWARE ON EQUIPMENT ; WHICH IS NOT SUPPLIED BY DIGITAL. .LIST .IIF DF NLOVLY, .NLIST ;UPDATE LEVEL 10 .SBTTL KMON OVERLAYS ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; THIS MACRO BEGINS A NEW KMON OVERLAY BLOCK ; IF NOT THE FIRST BLOCK, IT ROUNDS UP TO BLOCK BOUNDARY ; IT THEN INCREMENTS THE OVERLAY NUMBER, STARTS A NEW CSECT, ; AND DEFINES OVLYST TO BE THE BLOCK START .MACRO OVERLAY .IF GE OVLYN .IIF GT <.-OVLYST>-<1000*OVLYSZ>, .ERROR ;PREVIOUS OVERLAY TOO LARGE .=OVLYST+<1000*OVLYSZ> .ENDC OVLYN=OVLYN+OVLYSZ .IRP N,<\OVLYN> .CSECT OVLY'N .ENDR OVLYST=. .ENDM OVERLAY ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; THIS MACRO STARTS A KMON OVERLAY COMMAND ; IT DEFINES N.CMD TO BE THE BLOCK NUMBER OF THE MONITOR FILE ; IN WHICH THE COMMAND RESIDES, AND O.CMD TO BE THE (WORD) ; OFFSET IN THE BLOCK AT WHICH THE COMMAND STARTS .MACRO OVCMD CMD N.'CMD=OVLYN+RT11SZ+SWAPSZ O.'CMD=.-OVLYST CMD: .ENDM OVCMD ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; THIS MACRO GENERATES A CALL FR@M AN OVERLAY TO THE OUTSIDE WORLD ; IT COMPUTES THE PC-RELATIVE OFFSET FROM WHERE THE JSR WOULD ; BE IF THIS BLOCK WERE ACTUALLY IN THE KMON OVERLAY AREA .MACRO OJSR R,DEST JSR R,-<.+4-OVLYST>(PC) .ENDM OJSR ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; THESE MACROS ARE USED TO ACCESS LOCATIONS OUTSIDE THE OVERLAY ; REGION. THEY COMPUTE THE PC-RELATIVE ADDRESS AS IF THE INSTRUCTION ; WERE IN THE KMON OVERLAY AREA. .MACRO OCMP SRC,R CMP -<.+4-OVLYST>(PC),R .ENDM OCMP .MACRO OMOV SRC,R MOV -<.+4-OVLYST>(PC),R .ENDM OMOV .MACRO OADD SRC,R ADD -<.+4-OVLYST>(PC),R .ENDM OADD .MACRO OJMP DEST JMP -<.+4-OVLYST>(PC) .ENDM OJMP ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; THIS PERFORMS AN ADDR MACRO FROM AN OVERLAY BLOCK OF AN ADDRESS ; OUT IN THE REAL WORLD .MACRO OADDR ADR,REG,PUSH .IF IDN REG,SP MOV PC,-(SP) ADD #-<.-OVLYST>,(SP) .IFF .IF B PUSH MOV PC,REG .IFF JSR REG,(PC) .ENDC ADD #-<.-OVLYST>,REG .ENDC .ENDM OADDR .SBTTL DATE ; "THIRTY DAYS HATH SEPTEMBER, ; APRIL, JUNE, AND NOVEMBER; ; ALL THE REST HAVE THIRTY-ONE, ; EXCEPTING FEBRUARY ALONE, ; AND THAT HAS TWENTY-EIGHT DAYS CLEAR ; AND TWENTY-NINE IN EACH LEAP YEAR." ; - RICHARD GRAFTON,"ABRIDGEMENT OF THE CHRONICLES OF ENGLAND" OVERLAY OVCMD DATE .ENABL LSB ADDR MONTHS,R4 ;POINT TO ASCII MONTH NAMES MOV @#SYSPTR,R0 ;POINT TO MONITOR TSTB -1(R5) ;WANT TO PRINT IT ? BEQ 10$ ;YAH CLR R1 ;CLEAR DATE ACCUMULATOR JSR R3,NUMK ;GET DAY IN R1 .BYTE 0.,31.-0. SWAB R1 ;PUT IT IN PLACE ASR R1 ASR R1 ASR R1 INC R5 ;FIX AND MOV R5,R3 ;SAVE PTR TO -MON-YY 1$: ADD #2000,R1 ;BUMP DATE TO NEXT MONTH TSTB 1(R4) ;END OF LIST ? BEQ 90$ ; DRAT MOV R3,R5 ;POINT R5 TO GIVEN -MON- MOV R4,R2 ;COPY PTR INTO LIST CMP (R4)+,(R4)+ ;ADVANCE FOR NEXT TIME 2$: CMPB -(R5),(R2)+ ;OK SO FAR ? BNE 1$ ;NO, TRY NEXT MONTH CMP R2,R4 ;DONE 5 ? BLOS 2$ ;KEEP TRYING JSR R3,NUMK ;A MATCH! ADD IN YEAR .BYTE 72.,99.-72. MOV R1,$DATE-$RMON(R0) 9$: RTS PC 10$: MOV $DATE-$RMON(R0),R2 ;GET THE DATE BEQ 90$ ;NONE. DO NOT PRINT IT 11$: MOV @SP,R0 ;GET TOP VALUE MOV R2,-(SP) ;MAKE IT 3 5-BIT FIELDS BIC #177740,(SP) ASR R2 ASR R2 ASR R2 ASR R2 ASR R2 BNE 11$ JSR PC,R10ONF ;PRINT IT DEC @SP ;INDEX INTO TABLE ASL @SP ASL @SP ADD (SP)+,R4 ;R4 POINTS TO -MMM- MOV #5,R2 ;5 CHARS 12$: .TTYOUT (R4)+ DEC R2 BNE 12$ TST (SP)+ ;PURGE DAY MOV (SP)+,R0 ;GET YEAR ADD #72.,R0 ; (REL 1972) JSR PC,R10OUT ;PRINT IT K0CRLF: OJMP KCRLF ;PRINT CR LF 90$: KMEROR NUMK: OJSR PC,DECNUM ;GET A NUMBER MOVB (R3)+,R2 ;GET LOW LIMIT SUB R2,@SP ;DECREASE NUMBER BLE 90$ ;TOO BAD MOVB (R3)+,R2 ;GET UPPER LIMIT CMP @SP,R2 ;TOO BIG ? BGT 90$ ADD (SP)+,R1 ;ADD IT IN RTS R3 .DSABL LSB .SBTTL TIME OVCMD TIME .ENABL LSB MOV @#SYSPTR,R0 ;CHECK FOR EXISTANCE OF CLOCK ADD #CONFIG-$RMON,R0 ;POINT TO CONFIGURATION WORD TST @R0 ;DID THE BOOTSTRAP FIND A CLOCK? BPL 91$ ;NO, TELL HIM SO BIT #CLK50$,@R0 ;IS IT A 50-CYCLE CLOCK? BEQ 101$ ;NO, 60 CYCLES MOVB #50.,11$ ;YES, SET 50 CYCLES MOVB #50.,CLKFRQ .IF NE BF MOV #101,GTM.HI-CONFIG(R0) ;# OF 50 CYCLE TICKS MOV #165400,GTM.LO-CONFIG(R0) ;IN A DAY .ENDC 101$: ADDR TMRLST,R3 ;POINT TO LIST MOV R3,R0 ;COPY POINTER TO .GTIM AREA MOV R3,-(R0) ;PUT IN ADDRESS TST -(R0) ;POINT TO PARAM BLOCK EMT 375 ;DO .GTIM TSTB -1(R5) ;WANT TO PRINT IT ? BEQ 10$ ;YAH CMP (R3)+,(R3)+ CLR R1 ;TIMER ACCUMULATOR IS R1/@SP CLR -(SP) 1$: OJSR PC,DECNUM ;GET NEXT VALUE MOVB (R3)+,R4 ;GET MAXIMUM CMP R4,@SP ;TOO BIG ? BLOS 90$ ;YES CMPB @R5,(R3)+ ;PROPER DELIMITER ? BEQ 2$ ;YES TSTB @R5 ;IS IT THE NULL BYTE ? BNE 90$ ;BAD SYNTAX INC R5 ;KEEP USING NULL 2$: ADD (SP)+,@SP ;ADD IN LOW ORDER ADC R1 ;BUBBLE TO HIGH ORDER MOVB @R3,R4 ;END OF TIME ? BEQ 4$ ;YES MOV R1,R2 ;NO. MULTIPLY TIME BY FACTOR MOV @SP,R0 ;COPY TIME TO R2/R0 3$: DEC R4 ;DONE MULTIPLY ? BEQ 1$ ;YES ADD R0,@SP ADC R1 ADD R2,R1 BR 3$ 4$: MOV @#SYSPTR,R0 .IF NE BF SUB TMRLST+2,@SP SBC R1 SUB TMRLST,R1 ADD (SP)+,$TIME+2-$RMON(R0) ;FIX TIM OF DAY ADC R1 ADD R1,$TIME-$RMON(R0) .IFF CLR @#LKCS ;TURN OFF INTERRUPTS MOV (SP),$TIME+2-$RMON(R0) ;PUT IT INMONITOR MOV R1,$TIME-$RMON(R0) MOV #100,@#LKCS TST (SP)+ .ENDC K0RTS: RTS PC ;GO BACK 10$: MOV (R3)+,R1 ;GET TIME OF DAY MOV (R3)+,R2 ;LOW ORDER IN R2 JSR R4,DIVIDE ;FIRST DIVIDE OUT THE TICKS/SECOND 11$: .WORD CLOCK MOV R5,R0 ;PUT -1 IN R0 FOR FLAG MOV #3,R3 ;LOOP 3 TIMES 12$: MOV R0,-(SP) ;SAVE REMAINDER (OR FLAG) JSR R4,DIVIDE ;DIVIDE BY 60. .WORD 60. DEC R3 ;LOOP BNE 12$ 13$: JSR PC,R10OUT ;PRINT THE NUMBER IN R0 MOV (SP)+,R2 ;GET NEXT VALUE BMI K0CRLF ;IF NEGATIVE, DONE .TTYOUT #': ;PUT OUT A SEPARATOR MOV R2,R0 ;COPY VALUE BR 13$ ;LOOP 90$: KMEROR 91$: KMEROR .DSABL LSB .SBTTL DECIMAL OUTPUT AND CONVERSION .ENABL LSB R10ONF: CMP #10.,R0 ;IS THE NUMBER ONE DIGIT? BHI 2$ ;YES, PUT IT OUT AS ONE R10OUT: SWAB R0 ;PUT NUMBER IN HIGH BYTE 1$: ADD #173001,R0 ;SUBTRACT 10 FROM HIGH, ADD 1 TO LOW BPL 1$ ;LOOP UNTIL OVERFLOW ADD #'0+<10.*400-1>,R0 ;FIX BOTH BYTES, ASCIIFY THE LOW .TTYOUT ;PRINT HIGH DIGIT SWAB R0 ;GET OTHER DIGIT 2$: ADD #'0,R0 ;ASCIIFY IT .TTYOUT RTS PC .DSABL LSB .IF NE BF ; THESE ARE LINKS TO OVERLAY COMMANDS WHICH ARE TOO FAR AWAY OVCMD SAVEK JMP OSAVE OVCMD ASSIGN JMP OASSIGN .ENDC DIVIDE: CLR R0 ;REMAINDER MOV #31.,R5 ;32. BITS 1$: ASL R2 ;DOUBLE PRECISION DIVIDE ROL R1 ROL R0 CMP R0,@R4 BLO 2$ SUB @R4,R0 INC R2 2$: DEC R5 BPL 1$ TST (R4)+ ;PUSH OVER RADIX RTS R4 MONTHS: .ASCIZ "-JAN-FEB-MAR-APR-MAY-JUN-JUL-AUG-SEP-OCT-NOV-DEC-" .BYTE 0,..GTIM .WORD 0 TMRLST: .WORD 0,0 .BYTE 24.,':,60.,':,60.,'. CLKFRQ: .BYTE CLOCK,377,0 .EVEN .SBTTL SAVE .IF EQ BF OVERLAY OVCMD SAVEK .ENDC OSAVE: MOV #9.*400+8.,R4 ;COUNTERS IN R4 ADDR SAVBLK,R1 ;R1 -> INTERNAL COPY MOV @#USERTOP,(R1)+ ;SAVE A COPY OF THE TOP MOV @#SYSPTR,R3 ;R3 -> CCB IN RMON ADD #CCB-$RMON,R3 1$: MOV (R3)+,(R1)+ ;COPY A WORD DECB R4 BNE 1$ OJSR PC,GETHAN ;GET FILE NAME, HANDLER MOV R3,-(SP) ;SAVE POINTER TO FILE NAME TSTB @R5 ;IS IT EOL? BEQ DOSAVE ;YES, DO THE SAVE SWAB R4 ;GET COUNT OF 9 2$: CLR -(R1) ;CLEAR OUT TEMP CCB AND TEMP USERTOP DEC R4 BNE 2$ MOV R1,R3 ;R3 -> TEMP USERTOP 3$: TSTB @R5 ;END OF LINE? BEQ DOSAVE ;YES, NOW DO THE SAVE CMPB #' ,@R5 ;CHECK FOR ADDRESSES BEQ 103$ ;DELIMITED BY BLANK OR COMMA CMPB #',,@R5 BNE BADSAV ;NO, IT'S BAD 103$: JSR PC,SAVNUM ;GET A LOW ADDRESS MOV R4,R2 ;PUT IT IN R2 CMPB @R5,#'- ;IS IT A RANGE? BNE 4$ ;NO JSR PC,SAVNUM ;YUP, GET A HIGH ADDRESS CMP R4,R2 ;CHECK LEGALITY BLO BADSAV ;HIGH ADDRESS < LOW ADDRESS 4$: MOV R3,R0 ;COPY POINTER CMP (R0)+,R4 ;IS THIS THE LARGEST SO FAR? BHI 5$ ;NO MOV @#SYSPTR,R1 ;IS THIS TOO BIG FOR COMFORT? CMP R4,SYSLOW-$RMON(R1) BHIS BADSAV ;TRYING TO SAVE OUT OF RANGE MOV R4,@R3 ;SAVE TEMP USERTOP 5$: OJSR PC,NOTHIR ;SET BIT MAP (R0 -> TEMP BITMAP) BR 3$ ;AND TRY FOR MORE DOSAVE: OADDR KMON,R4 ;R4 -> KMON CLRB R4 ;ROUND DOWN TO A BLOCK BOUNDARY SWAB R4 ;MAKE IT A BLOCK COUNT ASR R4 MOV SAVBLK,R1 ;GET SAVE FILE'S USERTOP BEQ BADSAV ;CAN'T SAVE NOTHING CLRB R1 ;MAKE A BLOCK COUNT OF SAVE FILE SWAB R1 ASR R1 INC R1 ;DON'T FORGET THE LAST BLOCK MOV #3*400+17,R0 ;PURGE CH 17 EMT 374 .ENTER 17,(SP)+,R1 ;ENTER A FILE OF THE RIGHT SIZE BCS SAVERR ;OOPS, NO ROOM SUB R4,R1 ;R1 = COUNT OF BLOCKS IN SCRATCH AREA BPL 21$ ;THERE'S SOMETHING THERE ADD R1,R4 ;IT'S SHORTER THAN SCRATCH, ADJUST R4 21$: MOV #1000,R0 ;NOW COPY BLOCK 0 TO THE USR BUFFER OMOV .USRTOP,R3 CLR @<.BLKEY-OVLY>-<.+4-OVLYST>(PC) ;THE BUFFER IS DEAD 22$: MOV -(R0),-(R3) ;COPY IT TST R0 ;DOWN TO THE BEGINNING BNE 22$ ADDR SAVBLK,R2 ;POINT TO TEMP AREA MOV (R2)+,USERTOP(R3) ;PUT IN THE PROPER TOP ADDRESS MOV R3,R5 ;R3 -> USR BUFFER ADD #360,R5 ;R5 -> CCB IN USR BUFFER MOV #8.,R0 ;COUNT TO MOVE 23$: MOV (R2)+,(R5)+ DEC R0 BNE 23$ .WRITW 17,R3,#400 ;WRITE THE USR BUFFER AS BLOCK 0 (R0=0) BCS SAVERR ;OOPS DEC R4 ;COUNT DOWN BLOCKS TO DO BLE 40$ ;DONE ALREADY! CLR -(SP) ;WAIT I/O MOV R4,-(SP) ;BLOCK COUNT TO DO FROM IN CORE SWAB @SP ;WORD COUNT MOV #1000,-(SP) ;ADDRESS TO START WRITING MOV #1,R0 ;START AT BLOCK 1 EMT 220+17 ;WRITE BCS SAVERR ;OOPS CLR R3 ;CLEAR SCRATCH AREA BLOCK NUMBER 30$: DEC R1 ;ANY MORE TO DO IN SCRATCH AREA? BMI 40$ ;NO CLR -(SP) ;WAIT I/O MOV #1000,-(SP) ;NORMALLY DO 2 BLOCKS DEC R1 ;BUT IF ONLY ONE IS LEFT BPL 31$ ; THEN ASR @SP ; ONLY DO ONE 31$: OADDR SYSIOB+2,R5 ;R5 -> IOB FOR SCRATCH AREA MOV @SP,@R5 ;INSERT PROPER READ LENGTH MOV -(R5),-(SP) ;SAVE ADDRESS OF BUFFER MOV R3,R0 ;R3 HAS SYSTEM SCRATCH BLOCK # OJSR PC,SYSK ;DO THE READ MOV R4,R0 ;R4 = BLOCK NUMBER IN SAVE FILE EMT 220+17 ;WRITE BCS SAVERR ;OOPS TST (R3)+ ;BUMP SCRATCH BLOCK # BY 2 CMPB (R4)+,(R4)+ ;BUMP SAVE FILE BLOCK # BY 2 BR 30$ ;AND LOOP 40$: .CLOSE 17 ;DONE RTS PC ;SAY GOODBYE SAVNUM: MOV R5,-(SP) ;SAVE POINTER DEC @SP OJSR PC,OCTNUM ;GET A NUMBER MOV (SP)+,R4 ; IN R4 CMP (SP)+,R5 ;GOT ANYTHING? BEQ BADSAV ;NO, ERROR RTS PC BADSAV: KMEROR SAVERR: OJMP SFERR ;DO A SAVE FILE ERROR SAVBLK: .BLKW 9. .SBTTL ASSIGN .IF EQ BF OVCMD ASSIGN .ENDC .ENABL LSB OASSIGN:MOV #$SLOT,R1 ;SIZE OF SYSTEM TABLES OADDR BLOCK,R2 ;POINTER TO FD BLOCK MOV @#SYSPTR,R4 ;R4 -> RMON OJSR PC,GETNAM ;GET SYSTEM PERM NAME BEQ 10$ ;NONE. DO A DEASSIGN OF ALL 20$: TST (R2)+ ;SKIP SYSTEM NAME TSTB @R5 ;END OF COMMAND? BEQ HANERK ;YES, ILLEGAL COMMAND OJSR PC,GETNAM ;GET USER ASSIGNED NAME BEQ HANERK ;CAN'T HAVE NULL USER NAME MOV -2(R2),R5 ;SEARCH $PNAME FOR PERM NAME MOV R4,R0 ;COPY PTR TO RMON ADD #$PNAME-$RMON,R0 ;R0 -> $PNAME TABLE 1$: MOV R5,R3 ;COPY SEARCH OBJECT SUB (R0)+,R3 ;IS PERM NAME IN THIS GROUP? BLO 2$ ;PERM NAME WAS TOO BIG BEQ 4$ ;EXACT MATCH SUB (PC)+,R3 ;IS IT DV0-DV7 ? .RAD50 / 0/ BLO 2$ ;NO CMP R3,#7 BLOS 4$ ;YES IT IS 2$: DEC R1 ;ANY MORE TO TRY ? BNE 1$ ;YES ;CAN'T PLACE HIS PERM NAME HANERK: OJMP BADHAN ; 4$: MOV #$SLOT,R1 ;FOUND VALID NAME. PUT USER'S ADD #$UNAM2+<2*$SLOT>-$RMON,R4 ;POINT TO TOP OF TABLE ;OF USER NAMES. CLR R3 ;R3 WILL POINT TO FIRST NULL SLOT 5$: CMP (R2),-(R4) ;FIND THIS USER NAME IF IT IS BEQ 8$ ; ALREADY ASSIGNED TST (R4) ;ELSE SEE IF 0 ENTRY BNE 6$ ; AND IF SO MOV R4,R3 ; REMEMBER IT 6$: DEC R1 ;ANY MORE? BNE 5$ ;YES TST R5 ;WERE WE WANTING TO CLEAR USER NAME ? BEQ HANERK ;YES, BUT THERE WASN'T ONE THERE MOV R3,R4 ;NO, WANT TO SET IT. SLOT HANDY? BEQ HANERK ;NO ROOM IN TABLE MOV @R2,@R4 ;PUT USER NAME IN TABLE 7$: MOV R5,$UNAM1-$UNAM2(R4) ;PUT PERM NAME IN TABLE RTS PC 8$: TST R5 ;FOUND USER NAME. SET PERM OR CLR USER? BNE 7$ ;GO SET PERM NAME CLR @R4 ;CLEAR THE USER NAME RTS PC 10$: TSTB @R5 ;WAS THE LINE NULL? BNE 20$ ;NO, GET USER NAME TO BE DEASSIGNED ADD #$UNAM2-$RMON,R4 ;POINT TO USER NAMES 11$: CLR (R4)+ DEC R1 BNE 11$ RTS PC .DSABL LSB .SBTTL LOAD OVERLAY .IF NE BF OVCMD UNLOAD JMP UNLDIN OVCMD SPND TST (PC)+ ;CLEAR THE CARRY OVCMD RSUME SEC ;SET THE CARRY JMP SPNRSU ;ENTER SUSPEND/RESUME CODE OVCMD CLOSEK JMP CLOSEO OVCMD FRUN JMP OFRUN .IIF NDF BANDW, .NLIST .IF DF BANDW OVCMD TECO JMP TECOO OVCMD MAKE JMP MAKEO .ENDC .IIF NDF BANDW, .LIST .ENDC OVCMD LOAD .ENABL LSB 23$: OADDR DEVSTS,R2 ;POINT TO BUFFER AREA OJSR PC,GETNAM ;GET DEVICE NAME JSR PC,MAPIT ;MAP USER NAME TO PHYSICAL NAME CLR FTEMP .IF NE BF CLR R3 ;INIT JOB TO NOT OWNED CMPB #'=,(R5) ;ASSIGN COMING UP? BNE 20$ ;NO, SET TO UNOWNED CMPB #'B,-(R5) ;BACKGROUND? BEQ 8$ ;YES CMPB #'F,(R5) ;FOREGROUND JOB? BNE IMSG3 ;NO, ERROR TST (R3)+ ;SET JOB # 1 ; AT THIS POINT COULD TEST NEXT DIGIT FOR MULTIPLE FOREGROUND JOBS. 8$: INC R3 ;SET UP JOB ID DEC R5 ;SKIP OVER B OR F .ENDC 20$: MOV (R2),-(SP) ;SAVE DEVICE NAME .DSTAT R2,R2 ;GET STATUS BCS IMSG1 ;ERROR TST 4(R2) ;ALREADY RESIDENT? .IF NE BF BNE 5$ ;YES .IFF BNE 19$ ;ALREADY LOADED .ENDC MOV (SP)+,@R2 ;NAME TO BUFFER ; GET SIZE OF THE HANDLER, THEN ALLOCATE CORE AND FETCH IT. MOV 2(R2),R0 ;R0 = HANDLER SIZE MOV R2,-(SP) ;SAVE BUFFER ADDRESS MOV R3,-(SP) ;SAVE JOB NUMBER JSR PC,GETBLK ;GET CORE FROM HANDLER MOV (SP)+,R3 ;RESTORE JOB # BCC 3$ ;WAS KMON MOVED? SUB R0,R5 ;YES, RELOCATE SOME SUB R0,2(SP) ;ADDRESSES. SUB R0,(SP) 3$: MOV (SP),R0 ;POINT TO NAME AGAIN .FETCH R4 ;GET HANDLER IN CORE BCS IMSG0 ;ERROR, NO HANDLER MOV R4,FTEMP ;SAVE CORE PTR FOR ;RECOVERY ON ERROR ; PROTECT THE VECTORS OF THE NEWLY-LOADED DEVICE HANDLER. MOV @R4,R2 ;GET VECTOR ADDRESS BEQ 4$ ;NONE TO PROTECT MOV #1,R4 ;PROTECT TWO WORDS MOV @#SYSPTR,R0 ;POINT TO MAP BLOCK ADD #LOWMAP-$RMON,R0 ;TURN ON BITS OJSR PC,SETBT2 ;BY CALLING SETBIT 4$: .IF EQ BF BR 19$ .IFF MOV (SP)+,R2 ;POINT TO BUFFER AGAIN BR 20$ ;GET STATUS AGAIN ; NOW SEARCH $ENTRY FOR ALL DEVICES HAVING ENTRY POINTS ; MATCHING THE REQUESTED DEVICE'S ENTRY POINT. 5$: OMOV .$ENTR,R0 ;R0 -> $ENTRY TABLE CLR R1 ;CLEAR INDEX 6$: CMP 4(R2),(R0)+ ;ENTRY POINTS MATCH? BEQ 7$ ;YES, R1 NOW INDEX TO $PNAME 22$: TST (R1)+ ;NO, BUMP INDEX 2 CMP R1,#$SLOT*2 ;THRU THE TABLE? BLT 6$ ;NO, CONTINUE .ENDC IMSG2: MOV FTEMP,R4 ;R4 -> CORE ALLOC., IF ANY BEQ IMSG3 ;NONE, JUST MESG JSR PC,PUTBLK IMSG3: OJMP BADCOM ; IMSG0: JSR PC,PUTBLK ;RETURN TO FREE CORE LIST IMSG1: OJMP BADHAN .IF NE BF ; GET DEVICE UNIT # FROM SPECIFIED DEVICE NAME 7$: OMOV .$PNAM,-(SP) ;SP -> $PNAME TABLE ADD R1,(SP) ;(SP) -> SLOT IN $PNAME MOV 2(SP),R4 ;R4 = DEV. NAME/UNIT RAD50 SUB @(SP)+,R4 ;R4 = UNIT # RAD50 BEQ 9$ ;EXACT MATCH => UNIT 0 SUB (PC)+,R4 ;R4 = UNIT # OCTAL .RAD50 / 0/ CMP R4,#7 ;NO, UNIT > 7? BHI 22$ ;YES, TRY ANOTHER ; GOT UNIT NUMBER IN R4. NOW CHECK TO SEE IF IT IS THE SYSTEM ; UNIT OF THE SYSTEM DEVICE TYPE, WHICH CANNOT BE ATTACHED. 9$: MOV @#SYSPTR,R0 CMP 4(R2),R0 ;SYSTEM DEVICE? .DSABL LSB .ENABL LSB BLO 10$ ;NO, GO ON CMP SYUNIT-$RMON(R0),R4 ;YES, SYSTEM UNIT? BEQ IMSG1 ;YES, CAN'T ATTACH ; NOW THAT THE UNIT # IS KNOWN, A MASK CAN BE SET UP AND ; THE JOB ID PREPARED FOR INSERTION IN THE $OWNER TABLE. 10$: TST @R2 ;FILE STRUCTURED DEV? BPL 12$ ;NO MOV #17,FTEMP ;SET MASK FOR EVEN UNIT CLC ROR R4 ;UNIT/2 =BYTE # OF $OWNER BCC ESRCH ;C=1 IF ODD UNIT ASL R3 ;MOVE JOB ID CODE ASL R3 ;TO HIGH HALF BYTE ASL R3 ASL R3 MOV #360,FTEMP ;SET MASK FOR HIGH HALF BYTE BR ESRCH ; FOR NON-FILE STRUCTURED DEVICES, ALL UNITS ARE ASSIGNED ; TO THIS JOB. 12$: TST R3 ;UNASSIGNED? BEQ ESRCH ;YES, GO ON DEC R3 ;F OR B? BEQ 13$ ;MUST BE B MOV #21042,R3 ;ASSIGN ALL UNITS 13$: ADD #10421,R3 ; NOW SEARCH $ENTRY FOR ALL ENTRIES MATCHING THE SPECIFIED ; DEVICE ENTRY AND ASSIGN OWNERSHIP TO THEM. ESRCH: OMOV .$ENTR,R0 ;R0 -> $ENTRY CLR R1 ;INIT INDEX 15$: CMP 4(R2),(R0)+ ;ENTRIES MATCH? BEQ 16$ 22$: CMP (R1)+,(R1)+ ;BUMP INDEX BY 4 SINCE ;$OWNER HAS 2 WD ENTRIES CMP R1,#$SLOT*4 ;THRU THE TABLE? BLT 15$ ;DO SOME MORE BR 19$ ;YES, ALL DONE ; DETERMINE THE CORRECT HALF BYTE IN $OWNER TO SET THE ; OWNERSHIP INFORMATION. IN THE CASE OF NON-FILE STRUCTURED ; DEVICES ALL 8 UNITS ARE SET TO THE SAME OWNER. 16$: MOV R1,-(SP) ;SAVE INDEX OADD .$OWNE,R1 ;R1 -> $OWNER TABLE TST @R2 ;IS DEV FILE-STRUCTURED? BPL 18$ ;NO,SKIP THIS JAZZ ADD R4,R1 ;R1 -> BYTE TO MODIFY BICB FTEMP,(R1) ;CLEAR OWNERSHIP BISB R3,(R1) ;INSERT NEW OWNER 17$: MOV (SP)+,R1 ;RESTORE INDEX TO R1 BR 22$ ;DO ANOTHER 18$: MOV R3,(R1)+ ;SET ALL UNITS OWNED MOV R3,@R1 BR 17$ .ENDC 19$: TST (SP)+ ;CLEAR STACK TSTB (R5) ;END OF COMMAND STRING? BNE 21$ ;NO, MORE TO COME RTS PC ;YES, EXIT 21$: JMP LOAD .DSABL LSB FTEMP: .WORD 0 ;TEMPORARY STORE ; SUBROUTINE MAPS USER ASSIGNED DEVICE NAME TO PHYSICAL ; DEVICE NAME. ; ; R2 -> USER NAME (RAD50) ; R1,R3 DESTROYED MAPIT: OMOV .$UNAM,R1 ;R1 -> ASSIGN TABLE MOV #$SLOT+3,R3 ;R3 = # DEV. SLOTS + 3 1$: DEC R3 ;THRU THE TABLE? BEQ 2$ ;YES CMP (R2),(R1)+ ;FOUND A MATCH? BNE 1$ ;NO, TRY ANOTHER MOV $UNAM1-$UNAM2-2(R1),(R2) ;YES, REPLACE IT 2$: RTS PC ; GETBLK -- SUBROUTINE TO SEARCH FREE CORE LIST FOR A BLOCK EQUAL ; TO REQUESTED SIZE. IF NOT IN FREE CORE LIST, KMON/USR IS ; MOVED DOWN TO CREATE THE BLOCK. C IS SET IF KMON/USR WAS MOVED. ; ; CALL SEQUENCE: JSR PC,GETBLK ; R0=# BYTES DESIRED ; ; RETURNS WITH: R4 -> START OF BLOCK+2 ; (R4)-2 = SIZE OF BLOCK (1ST WORD OF BLK) ; ; R1,R3 DESTROYED ; GETBLK: TST (R0)+ ;ADD 2 BYTES TO REQUEST OMOV .CORPT,R3 ;R3 -> FREE CORE LIST HEAD 1$: MOV 2(R3),R4 ;R4 -> NEXT FREE BLOCK OCMP .CORPT,R4 ;END OF LIST? BEQ 4$ ;YES, BACK AT LIST HEAD CMP (R4),R0 ;THIS BLOCK BIG ENOUGH? BGE 2$ ;YES, USE IT. MOV R4,R3 ;NO, TRY NEXT BLOCK BR 1$ 2$: SUB R0,(R4) ;BLK SIZE - REQUEST SIZE BNE 3$ ;EXACTLY THE SAME? MOV 2(R4),2(R3) ;YES, REMOVE FROM LIST 3$: ADD (R4),R4 ;R4 -> START OF BLOCK CLC BR 5$ ;GO EXIT 4$: SUB R0,(SP) ;RELOCATE RETURN ADDR. NEG R0 ;-SIZE => MOVE KMON DOWN ROR R0 ;HALVE IT, C=1 SO IT IS <0 OJSR PC,KUMOVE ;CALL TO MOVE KMON/USR NEG R0 ;FIX R0, SET CARRY 5$: MOV R0,(R4)+ ;STORE SIZE IN FIRST WORD RTS PC ; PUTBLK -- RETURNS A BLOCK OF CORE TO THE FREE CORE LIST. ; MERGES CONTIGUOUS BLOCKS OF CORE INTO A SINGLE BLOCK. ; RECLAIMS CORE FROM BLOCKS CONTIGUOUS TO KMON/USR BY ; SLIDING UP KMON/USR. C IS SET IF KMON/USR WAS MOVED. ; ; CALL SEQUENCE: JSR PC,PUTBLK ; ; R4 -> START OF BLOCK+2 ; (R4)-2 = SIZE OF BLOCK (IN 1ST WORD OF BLK) ; ; R0,R1 DESTROYED ; PUTBLK: TST -(R4) ;POINT TO BLOCK SIZE IN 1ST WD. OMOV .CORPT,R0 ;R0 -> FREE CORE LIST HEAD 1$: MOV 2(R0),R1 ;R1 -> NEXT FREE BLOCK OCMP .CORPT,R1 ;LAST BLOCK IN LIST? BEQ 3$ ;YES, INSERT NEW BLOCK HERE CMP R1,R4 ;NO, NEXT BLOCK HIGHER IN CORE? BHI 2$ ;YES, INSERT BLOCK HERE MOV R1,R0 ;NO, R0 -> CURRENT BLOCK BR 1$ ;CONTINUE SEARCH ; UPPER BOUNDARY CHECK FOR CONTIGUOUS BLOCKS 2$: MOV R4,-(SP) ;COMPUTE ADDR OF END OF ADD (R4),(SP) ;NEW BLOCK OF CORE. CMP (SP)+,R1 ;TOUCHES NEXT BLOCK? BNE 3$ ;NO, CAN'T MERGE ADD (R1),(R4) ;YES, MERGE THE TWO MOV 2(R1),2(R4) ;BLOCKS INTO ONE. BR 4$ ;THE CHECK LOWER BOUND. 3$: MOV R1,2(R4) ;JUST LINK IN NEW BLK ; LOWER BOUND CHECK FOR CONTIGUOUS BLOCKS 4$: MOV R0,-(SP) ;IS NEW BLOCK CONTIGUOUS ADD (R0),(SP) ;WITH LOWER BLOCK? CMP (SP)+,R4 ;COMPARE BOUNDS BEQ 5$ ;CONTIGUOUS, SO MERGE THEM MOV R4,2(R0) ;NO, JUST LINK TO LOWER BR 6$ ;THEN GO ON 5$: ADD (R4),(R0) ;ADD SIZES TOGETHER MOV 2(R4),2(R0) ;AND RE-LINK THE LIST. ; CORE RECLAIM CHECK 6$: OMOV .CORPT,R0 ;R0 -> FREE CORE LIST HEAD MOV 2(R0),R1 ;R1 -> LOWEST FREE BLOCK MOV @<.SYSLO-OVLY>-<.+4-OVLYST>(PC),-(SP) CMP (SP)+,R1 ;CONTIGUOUS TO USR? CLC BNE 7$ ;NO, JUST EXIT BIT (R1)+,(R0)+ ;BUMP R1, R0, LEAVE C=0 MOV (R1),(R0) ;REMOVE FROM LIST MOV -(R1),R0 ;SIZE IN R0 ROR R0 ;HALVE IT, LEAVE > 0 OJSR PC,KUMOVE ;THEN SQUISH IT ADD R0,(SP) ;RELOCATE RETURN ADDRESS SEC 7$: RTS PC ;AND EXIT .SBTTL UNLOAD .IF EQ BF OVCMD UNLOAD .ENDC UNLDIN: OADDR DEVSTS,R2 ;POINT TO NAME BLOCK OJSR PC,GETNAM ;GET DEVICE NAME BEQ 23$ ;NULL NAME? MOV R2,R0 ;R0 -> NAME BLOCK MOV R5,-(SP) ;SAVE PLACE IN COMMAND MOV @#SYSPTR,R5 ;POINT TO RMON .IF NE BF MOV FCNTXT-$RMON(R5),R4 ;POINT TO CONTEXT BEQ 1$ ;NOPE, NO JOB IN CORE BIT #NORUN$,@R4 ;IS IT STILL ALIVE? BEQ FJERR ;YES, CAN'T TOUCH ANYTHING! 1$: CMP @R2,(PC)+ ;IS IT A SPECIAL UNLOAD FG? .RAD50 /FG / BEQ 30$ ;YES, GO UNLOAD THE FG .ENDC JSR PC,MAPIT ;MAP NAME TO PHYSICAL NAME CMP @R2,(PC)+ ;TRYING TO UNLOAD BATCH? .RAD50 /BA / BNE 2$ ;NO, SAFE TO PROCEDE CMP LST16-$RMON(R5),#T$TIN-LST16 ;IS BATCH STILL HOOKED IN? BNE 22$ ;YES, A WISE GUY! 2$: OJSR R4,LK4DEV ;LOOK FOR DEVICE BR 22$ ;ERROR DURING SEARCH MOV @R5,R4 ;HANDLER RESIDENT? BEQ 20$ ;NO, NOTHIN TO DO CLR R1 ;INITIALIZE INDEX OMOV .$ENTR,R0 ;R0 -> $ENTRY TABLE 3$: CMP R4,@R0 ;ENTRIES MATCH? BNE 4$ ;NO, TRY THE NEXT .IF NE BF MOV R1,R3 ;YES, GET INDEX OADD .$OWNE,R3 ;R3 -> SLOT IN $OWNER CLR (R3)+ ;CLEAR ALL OWNERSHIP CLR @R3 ;FROM 8 UNITS .ENDC CMP @#SYSPTR,@R0 ;IS DEVICE THE SYSTEM DEV? BLOS 4$ ;YES, LEAVE IT BE CLR @R0 ;ZERO ENTRY 4$: TST (R0)+ ;BUMP TO NEXT DEVICE CMP (R1)+,(R1)+ ;BUMP OWNER INDEX BY 4 BYTES CMP R1,#$SLOT*4 ;THRU THE TABLE? BLT 3$ ;NO, DO ANOTHER ; NOW ELIMINATE THE HANDLER, RETURNING CORE TO THE FREE LIST. CMP @#SYSPTR,R4 ;SYSTEM DEVICE? BLOS 20$ ;YES, SKIP THIS CMP -(R4),-(R4) MOV -(R4),R0 ;R0 = HANDLER VECTOR ADDR CLR (R0)+ ;CLEAR VECTOR AND PRIORITY CLR (R0) JSR PC,PUTBLK ;RETURN TO LIST BCC 20$ ;KMON/USR MOVED? ADD R0,(SP) ;YES, RELOC. SOME PTRS. ADD R0,2(SP) ; DONE WITH THIS DEVICE - IS THERE ANOTHER? 20$: MOV (SP)+,R5 ;R5 -> COMMAND LINE 21$: TSTB (R5) ;MORE COMING? BNE UNLDIN ;YES RTS PC ;NO, JUST EXIT 22$: OJMP BADHAN ; 23$: OJMP BADCOM ; .IF NE BF ; THIS CODE UNLOADS AN INACTIVE FOREGROUND JOB THAT HAS ; BEEN ABORTED AND IS JUST LAYING AROUND. IT CLEARS OUT ; THE NECESSARY RMON POINTERS AND RECLAIMS THE CORE FOR USE ; BY THE SYSTEM. 30$: TST R4 ;F JOB IN CORE BEQ NOFERR ;NO, CAN'T DO IT CLR FCNTXT-$RMON(R5) ;MAKE THE FG VANISH BIC #FJOB$,CONFIG-$RMON(R5) ;SAY NO FG JOB JSR PC,PUTBLK ;THROW THE BUM OUT BCC 20$ ;NOTHING MOVED ADD R0,2(SP) ;FIX RETURN ADDRESS TO MONITOR ADD R0,@SP ;RECOVER AND RELOCATE R5 BR 20$ ;CONTINUE COMMAND NOFERR: KMEROR FJERR: KMEROR .ENDC .SBTTL CLOSE .IF EQ BF OVCMD CLOSEK .ENDC CLOSEO: OADDR HANDLR,R5 ;POINT R5 TO HANDLER SPACE OMOV .$CSW,R2 ;POINT TO CHANNEL TABLE MOV (PC)+,R4 ;SET UP CHANNEL 0 CLOSE .CLOSE 0 ;PROTOTYPE CLOSE 1$: MOV @R2,R0 ;TEST IF A FILE EXISTS ON CHANNEL BPL 3$ ;>0 IMPLIES NO FILE THERE BIC #177701,R0 ;ISOLATE INDEX . ADD @#SYSPTR,R0 ;POINT TO PERMANENT NAME ADD #$PNAME-$RMON,R0 MOV R0,-(SP) ;SAVE POINTER TO DEVICE NAME .FETCH R5 ;RE-FETCH DEVICE REQUIRED BCS CLSERR ;HANDLER FETCH FAILED MOV R4,(PC) ;SET UP THE EMT HALT ;GETS A CLOSE EMT MOV (SP)+,R0 ;POINT TO DEVICE AGAIN .RELEASE ;MAKE IT VANISH 3$: INC R4 ;NEXT CHANNEL ADD #12,R2 ;POINT TO NEXT CHANNEL CMP R4,(PC)+ ;DONE YET ? .CLOSE 20 BLO 1$ ;NO .SRESET ;CLEAR OUT ALL HANDLERS AGAIN RTS PC ;AND RETURN CLSERR: KMEROR .IIF NDF BANDW, .NLIST .IF DF BANDW .IF NE BF TECOO: TST (PC)+ ;CLEAR CARRY MAKEO: SEC ;SET THE CARRY MOV #510,R0 ;POINT TO PARAMETER AREA MOV R0,R1 ;COPY IT 1$: MOVB -(R5),(R0)+ ;MOVE IN THE FILE NAME BNE 1$ RORB -(R0) ;SET MAKE INDICATOR BPL 2$ ;IF NOT "MAKE", SKIP LOVELY TEST CMP (R1)+,(PC)+ .ASCII "LO" BNE 2$ CMP (R1)+,(PC)+ .ASCII "VE" BNE 2$ CMP R0,R1 BHI 2$ ADDR 10$,R0 ;IT'S LOVE .PRINT 2$: ADDR 11$,R1 ;POINT TO FILE TO CHAIN MOV @#SYSPTR,R2 ;TEST FOR DISPLAY HARDWARE BIT #HWDSP$,CONFIG-$RMON(R2) BEQ 3$ ;NONE, USE TECO MOV #3*400+17,R0 ;PURGE CH 17 EMT 374 ;NO ERRORS POSSIBLE .LOOKUP 17,R1 ;DO WE HAVE GTECO? BCC 4$ ;YES. USE IT 3$: ADD #12$-11$,R1 ;USE TECO 4$: .SRESET ;RESET ALL MOV #500,R0 ;MOVE IN FILE NAME MOV (R1)+,(R0)+ MOV (R1)+,(R0)+ MOV (R1)+,(R0)+ MOV (R1)+,(R0)+ MOV #10*400,R0 ;CHAIN AWAY EMT 374 10$: .ASCIZ /NOT WAR?/ .EVEN 11$: .RAD50 /SY GTECO SAV/ 12$: .RAD50 /SY TECO SAV/ .ENDC .ENDC .IIF NDF BANDW, .LIST .IF EQ BF .NLIST ;DO NOT LIST SUS/RSU OR FRUN IF SJ MONITOR .IFF .SBTTL SUSPEND / RESUME SPNRSU: MOV @#SYSPTR,R1 ;POINT TO MONITOR MOV FCNTXT-$RMON(R1),R1 ;POINT TO FG IMPURE AREA BEQ 90$ ;OOPS, NO FOREGROUND BCS 1$ ;GO IF RESUME BIS #KSPND$,@R1 ;SET SUSPENSION BIT IN FG STATUS RTS PC ;RETURN 1$: BIC #KSPND$,@R1 ;CLEAR THE SUSPENSION BIT .EXIT ;LEAVE THIS WAY TO FORCE CONTEXT SWITCH 90$: KMEROR .SBTTL FRUN ; THIS IS THE FIRST PART OF FRUN STA=40 ;PROGRAM REL. START ADDR. STK=42 ;INITIAL STACK SETTING RSZ=52 ;DISPL. TO ROOT SIZE OSZ=54 ;DISPL. TO OVERLAY SIZE RID=56 ;REL FILE I.D. LOCATION RBD=60 ;DISPL. TO FIRST REL BLOCK FCHNM=16. ;NO. OF F JOB CHANNELS FMPUR=FCHNM*10.+IMPSIZ+10 ;SIZE OF F JOB IMPURE AREA FJOBNM=2 ;FOREGROUND JOB NUMBER OFRUN: MOV @#SYSPTR,R0 ;POINT TO RMON MOV FCNTXT-$RMON(R0),R4 ;GET F CONTEXT BEQ 1$ ;ZERO => NO F JOB IN CORE BIT #NORUN$,@R4 ;F JOB IN, IS IT ACTIVE? BEQ FJERR ;YES, GIVE AN ERROR CLR FCNTXT-$RMON(R0) ;VANISH BIC #FJOB$,CONFIG-$RMON(R0) ;SAY F JOB GONE JSR PC,PUTBLK ;RECOVER CORE FROM DEAD F JOB BCC 1$ ;WAS KMON/USR MOVED? ADD R0,(SP) ;YES, RELOC RETURN ADDR ADD R0,R5 ;AND STRING POINTER 1$: MOV (PC)+,R3 ;DEFAULT DEV. IS DK .RAD50 /DK / OJSR PC,RFILE ;GET FILE DESCRIPTOR OJSR PC,GETHAR ;AND HANDLER .LOOKUP 17 ;FIND FILE ON CHAN. 17 BCC 2$ ;O.K., CONTINUE OJMP NOTFND ;GIVE FILE NOT FOUND ERROR 2$: MOV @#SYSPTR,R3 ;POINT TO MONITOR MOV $CSW+<15.*5*2>-$RMON(R3),R3 ;GET CHANNEL 17 STATUS BIC #177701,R3 ;ISOLATE DEVICE INDEX OADD .$ENTRY,R3 ;R3 -> ENTRY FOR FRUN DEVICE CMP @<.SYSLO-OVLY>-<.+4-OVLYST>(PC),@R3 ;SYSTEM OR LOADED? BHI 3$ ;NO, FETCHED. LEAVE POINTER ALONE CLR R3 ;CLEAR POINTER SO FRUN WON'T RELOCATE 3$: MOV R3,-(SP) ;PRESERVE IT OVER THE LINK OVLINK FRU2 ;LINK TO THE REST OF THE COMMAND .SBTTL FRUN (PART 2) OVERLAY OVCMD FRU2 .ENABL LSB MOV (SP)+,FRDEV ;RECOVER POINTER TO $ENTRY CLR PSWICH ;INIT SWITCH DATA CLR NVAL MOV #200*2,SVAL 1$: TSTB @R5 ;ANY SWITCHES COMING? BEQ 6$ ;NO, ALL DONE CMPB #'/,(R5) ;IS IT A /? BNE 4$ ;NO MOVB -(R5),R0 ;R0=SWITCH BEQ 4$ ;CR IS AN ERROR CMPB #'P,R0 ;P SWITCH? BEQ 5$ ;YES, PROCESS IMMED. CMPB #':,-(R5) ;OTHERS MUST HAVE VALUES BEQ 2$ ;: => OCTAL CMPB #'!,@R5 ;WHILE ! -> DECIMAL BNE 4$ ;NEITHER IS AN ERROR SEC ;SET C FOR DECIMAL 2$: OJSR PC,CVTNUM ;RETURNS VALUE IN STACK BCS 4$ ;WAY TOO BIG ASL (SP) ;CONVERT TO BYTES CMP #'N,R0 ;N SWITCH? BNE 3$ ;NO MOV (SP)+,(PC)+ ;SAVE IT NVAL: .WORD 0 BR 1$ 3$: CMP #'S,R0 ;S SWITCH? BNE 4$ ;THEN AN ERROR MOV (SP)+,(PC)+ ;SAVE IT SVAL: .WORD 0 ;# BYTES STACK SPACE ;ALSO TEMP. STORAGE BNE 1$ ;MUST BE NON-ZERO 4$: OJMP BADCOM ;KMEROR 5$: INC (PC)+ ;SET P SWITCH FLAG PSWICH: .WORD 0 ;PRINT BASE ADDR FLAG TSTB -(R5) BNE 1$ ;THEN LOOK FOR MORE 6$: OMOV .USRBU,R5 ;R5 -> USR BUFFER CLR @<.BLKEY-OVLY>-<.+4-OVLYST>(PC) ;NO DIRECTORY IN CORE MOV R5,RELBUF ;READ INTO USR BUFFER .DSABL LSB ; READ BLOCK 0 OF THE REL FILE -- THE PSEUDO CCB FOR REL FILES. CLR STMPUR ;NO CORE ALLOC. YET CLR RELBLK ;BLOCK # 0 JSR PC,RDBK0 ;READ INTO USR BUFFER .WAIT 17 ;WAIT FOR READ ; COMPUTE TOTAL PROGRAM CORE REQUIREMENTS AND ALLOCATE SPACE .ENABL LSB GETADR: MOV R5,R3 ;POINT R3 TO SIZE OF ADD #RSZ,R3 ;ROOT IN CCB0 MOV (R3)+,R4 ;R4 = SIZE OF ROOT SEGMENT MOV #FMPUR,R2 ;R2 = SIZE OF IMPURE AREA MOV STK(R5),-(SP) ;DID USER SPECIFY A STACK PTR? BNE 1$ ;YES ADD SVAL,R2 ;NO,ADD STACK SIZE 1$: MOV R2,-(SP) ;SAVE PROG. BASE OFFSET ADD R4,R2 ;R2 = OFFSET TO OVLY REGION ROR R4 ;CONVERT ROOT SIZE TO WORDS MOV R4,OVSIZ ;AND SET IN I/O BLOCK MOV R2,-(SP) ;SAVE OFFSET FOR OVLY I/O BLOCK ADD (R3)+,R2 ;R2 = PROG. HIGH LIMIT CMP (PC)+,(R3)+ ;IS THIS A REL FILE? .RAD50 /REL/ BEQ 2$ ;YES JMP FERR3 ;NO, ERROR EXIT 2$: MOV (R3),RELBLK ;SAVE REL BLK PTR MOV NVAL,R0 ;GET REQUESTED FREE CORE ADD R2,R0 ;ADD IMPURE AREA & PROG SIZE JSR PC,GETBL3 ;ALLOCATE SOME CORE BCC 3$ ;WAS KMON/USR MOVED? SUB R0,R5 ;YES, RELOCATE POINTERS SUB R0,6(SP) MOV (PC)+,R1 ;GET POINTER TO DEVICE HANDLER FRDEV: .WORD 0 BEQ 3$ ;SYSTEM OR LOADED, DON'T RELOCATE SUB R0,@R1 ;FETCHED. RELOCATE IT MOV @R1,R1 ;POINT TO RELOCATED HANDLER SUB R0,@-6(R1) ;RELOCATE ITS VECTOR ; CLEAR IMPURE AREA BEFORE INITIALIZING 3$: MOV #FMPUR/2,R0 ;CLEAR IMPURE AREA MOV R4,R1 ;R1 -> IMPURE AREA 4$: CLR (R1)+ DEC R0 BNE 4$ ; SAVE CONTENTS OF CCB 34-50 ON STACK FOR LATER USE ADD R4,(SP) ;RELOC OVLY OFFSET MOV (SP)+,SVAL ;SAVE TEMP. IN SVAL MOV (SP)+,R0 ;R0 = PROG. BASE OFFSET MOV (SP)+,R3 ;STACK SPECIFIED? BNE 5$ ;YES MOV R0,R3 ;SET UP STACK PTR VALUE 5$: ADD R4,R2 ;R2 = TOP OF PROGRAM MOV R5,R1 ;MAKE R1 -> 34(R5) ADD #34,R1 ADD R4,R0 ;RELOC PROG BASE ADDR MOV R0,STOVL ;SET IN I/O BLOCK TST PSWICH ;PRINT LOAD ADDRESS? BEQ 6$ ;NO MOV R0,PSWICH ;YES,THEN SAVE IT 6$: ADD R4,R3 ;RELOC. STACK PTR MOV R3,-(SP) ;THEN SAVE IT. CLR -(R3) ;DUMMY PSW ON STACK MOV R0,-(R3) ;SET F JOB PC TO ADD STA(R5),@R3 ;START ADDRESS ADD #-14,R3 ;BUMP PAST REG SAVE AREA MOV (R1)+,-(R3) ;SAVE 34 & 36 ON STACK BEQ 7$ ;TRAP ADDR SPECIFIED? ADD R0,(R3) ;YES, RELOCATE IT 7$: MOV (R1)+,-(R3) MOV (R1)+,-(R3) ;GET F JOB START ADDR ADD R0,(R3) ;RELOCATE IT MOV (SP)+,-(R3) ;STORE F JOB STACK PTR TST (R1)+ ;BUMP R1 UP TO 44(R5) MOV (R1)+,-(R3) ;SAVE F JSW MOV (R1)+,-(R3) ;SAVE USR AREA BEQ 8$ ;WAS IT SPECIFIED? ADD R0,(R3) ;YES, RELOCATE IT 8$: MOV R2,-(R3) ;STORE F JOB HI LIMIT MOV R2,-(SP) ;SAVE FOR STRTPG ADD NVAL,(SP) ;ADD FREE SPACE CLR -(R3) ;CLEAR 52(R5) MOV R3,I.SP(R4) ;SAVE STACK VALUE IN IMPURE AREA .DSABL LSB ; THIS CODE SETS UP AND RELOCATES THE POINTERS TO THE USR ; BUFFER USED BY THE REL BLOCK DOUBLE BUFFER LOGIC. ADDR BUFR1,R1 ;SET UP BUFFER POINTERS MOV #1000,R2 MOV R1,R0 MOV R1,-(R0) ;FIRST REL BLK IN BUFR2 MOV R5,(R1)+ ;SET UP BUFR1 MOV R5,(R1)+ MOV R2,@R1 ADD R2,-(R1) MOV (R1)+,R2 ADD R2,(R1)+ MOV R1,@R1 ADD #2,(R1)+ MOV R2,(R1)+ MOV R5,(R1)+ MOV R2,(R1)+ MOV @R0,@R1 ; IMPURE AREA INITIALIZATION -- THE F JOB IMPURE AREA PLACED ; BELOW THE ROOT SECTION OF THE PROGRAM MUST BE INITIALIZED. ; THIS AREA CONTAINS THE TTY RING BUFFERS, I/O QUEUE ELEMENTS, ; I/O CHANNELS AND CONTEXT INFORMATION. THE DISPLACEMENTS USED ; ARE DEFINED IN RMON. MOV R4,(PC)+ ;SAVE START OF IMPURE AREA STMPUR: .WORD 0 ;START OF IMPURE AREA MOV R4,R2 ;R4 -> START OF IMPURE AREA ADD #I.QUE,R2 ;R2 = ADDR. OF F QUEUE AREA MOV R2,I.QHDR(R4) ;SET UP Q PTR MOV #FJOBNM,I.JNUM(R4) ;SET UP JOB # MOV #FCHNM,I.CNUM(R4) ;AND NO. OF CHANNELS ADD #I.SERR+6-I.QUE,R2 ;R2->START OF JOB I.D. AREA MOV R2,I.TID(R4) ;SAVE IN JOB I.D. PTR MOV (PC)+,(R2)+ ;INSERT F JOB ID .BYTE CR,LF MOV (PC)+,(R2)+ .BYTE 'F,'> MOV (PC)+,(R2)+ .BYTE CR,LF CLR (R2)+ MOV R2,I.CSW(R4) ;STORE IN CH. PTR ADD #15.*5*2,R2 ;R2 -> FG CH 15. MOV #$CSW+<15.*5*2>-$RMON,R1 ;R1=DISP TO CH 15. ADD @#SYSPTR,R1 ;R1 -> BG CH 15. .REPT 5 MOV (R1)+,(R2)+ ;MOVE CH 15 TO FG (FOR OVLYS) .ENDR MOV R2,-(SP) ;SAVE F JOB LO LIMIT MOV R4,R2 ADD #I.ITOP+2,R2 ;R2 -> INPUT RING MOV R2,I.IRNG(R4) ;SET UP INPUT RING PTRS. MOV R2,I.IPUT(R4) MOV R2,I.IGET(R4) ADD #TTYIN,R2 ;R2 -> END OF INPUT RING MOV R2,I.ITOP(R4) ADD #I.OTOP-I.ITOP-TTYIN,R2 ;R2 -> OUTPUT RING MOV R2,I.OPUT(R4) ;SET UP OUTPUT RING PTRS. MOV R2,I.OGET(R4) ADD #TTYOUT,R2 ;R2 -> END OF OUTPUT RING MOV R2,I.OTOP(R4) MOV #ACTIV$+,I.MSG(R4) ;SET UP ;MESSAGE CHANNEL FOR F JOB. ; READ ROOT PROGRAM SECTION INTO CORE ADDR OVBK,R0 ;R0 -> I/O BLOCK MOV R0,-(SP) ;SAVE ON STACK MOV #1,@R0 ;ROOT ALWAYS IN BLK #1 MOV #10*400+17,-(R0) ;SET TO READ EMT 375 FERR0: BCS FERR1 ;GO RELOC ROOT ; SET UP TO RELOCATE THE ROOT SEGMENT NOW IN CORE RELSET: MOV STOVL,R1 ;R1=PROGRAM BASE JSR PC,RDBUF ;READ FIRST REL BLOCK MOV R4,R5 ;R4 SAME AS R5 ;TO TRIGGER A RDBUF ON ;1ST ENTRY TO GETWD. MOV SVAL,STOVL ;SET OVLY REGION ADDR IN I/O BLK CLR FLG2 ;MAKE SURE ITS CLEAR ; NOW RELOCATE THE ROOT SEGMENT .ENABL LSB 1$: JSR PC,GETWD ;GET A WD BCS ENDRUT ;-1 OR -2 RETURN MOV R2,R0 ;COMPUTE CORE ADDR TO RELOC ASL R0 ;CONVERT TO WORD BOUNDARY ADD R1,R0 ;R0 NOW -> WORD IN CORE JSR PC,RELOC ;RELOC THE WORD BR 1$ ;THEN DO ANOTHER ; READ AN OVERLAY SEGMENT INTO CORE WORK AREA. AFTER ; RELOCATING THE OVERLAY SEGMENT, IT WILL BE WRITTEN BACK ; INTO THE FILE FOR LOADING BY THE RESIDENT OVERLAY HANDLER. 2$: JSR PC,OVREL ;RELOCATE A WD 3$: JSR PC,GET2WD ;GET 2 REL WORDS BCC 2$ ;-1 OR -2 RETURN MOV (SP),R0 ;R0 -> I/O BLOCK BIS #400,-(R0) ;CHANGE READ CODE TO WRITE EMT 375 BCS FERR1 ENDRUT: TST FLG2 ;END OF ALL REL BLOCKS? BNE STRTPG ;YES, START THE PROG JSR PC,GET2WD ;NO, SET UP AN OVERLAY MOV (SP),R0 ;R0 -> OVBK MOV R2,@R0 ;SAVE OVERLAY BLOCK # MOV R3,OVSIZ ;AND THE SIZE MOV #10*400+17,-(R0) ;SET TO READ CODE EMT 375 BCC 3$ ;THEN GO RELOC FERR1: MOV STMPUR,R4 ;POINT R4 TO AREA BEQ FERR3 ;NONE ALLOC. YET JSR PC,PUTBL3 ;RELEASE CORE FERR3: KMEROR .DSABL LSB .ENABL LSB ; RELOCATE THE OVERLAY SEGMENT IN THE WORK AREA. OVREL: MOV R2,R0 ;MAKE R0 -> LOC TO RELOC ASL R0 ;ADJUST R0 TO WORD BOUNDARY ADD STOVL,R0 ;RELOC PTR MOV R3,@R0 ;SET UP TEXT IN CORE RELOC: ASL R2 ;EXTRACT RELOCATION SIGN BCS 1$ ;NEGATIVE RELOC? ADD R1,@R0 ;NO, ADDITIVE RELOC RTS PC 1$: SUB R1,@R0 2$: RTS PC ; SET UP FOREGROUND JOB LIMITS AND IMPURE POINTERS IN RMON. ; RETURN TO KMON WILL CAUSE CONTEXT SWITCHING TO ACTIVATE ; THE FOREGROUND JOB. STRTPG: TST (SP)+ ;POP OFF OVBK PTR MOV @#SYSPTR,R3 ;POINT TO RMON BIS #FJOB$,CONFIG-$RMON(R3) ;SAY F JOB IS IN MOV (SP)+,$JBLIM+<2*FJOBNM>+2-$RMON(R3) ;SET LOW LIMIT MOV (SP)+,$JBLIM+<2*FJOBNM>-$RMON(R3) ;AND F JOB HI LIMIT MOV STMPUR,$IMPUR+FJOBNM-$RMON(R3) ;AND SET IT UP MOV PSWICH,R2 ;R2= PROG.BASE ADDRESS BEQ 2$ ;PRINT IF NON-ZERO BIS #KSPND$,@STMPUR ;P SWTCH => FJOB SUSPENDED ADDR PMSG,R0 .PRINT CLR R1 ;SET UP TO ENTER OCTAL ;PRINT ROUTINE IN KMON. OJMP OPRINT .DSABL LSB ; THE FOLLOWING IS THE OVERLAY I/O BLOCK FOR READ/WRITE I/O. OVIOBK: .BYTE 17 ;CHANNEL 17 .BYTE 10 ;READ=10, WRITE=11 OVBK: .WORD 0 ;CURRENT OVERLAY BLOCK # STOVL: .WORD 0 ;START OF OVERLAY REGION OVSIZ: .WORD 0 ;CURRENT OVERLAY WORD SIZE .WORD 0 ;WAIT I/O FLG2: .WORD 0 ;END OF REL FLAG (IF NON-ZERO) ; FOLLOWING IS I/O BLOCK FOR READING REL BLOCKS RLIOBK: .BYTE 17,10 ;CH. 17;READ RELBLK: .WORD 0 ;CURRENT REL BLOCK RELBUF: .WORD 0 ;CURRENT BUFFER PTR .WORD 400,1 ;400 WORDS;DON'T WAIT PMSG: .ASCII "LOADED AT "<200> .EVEN ; SUBROUTINE TO GET ONE WORD FROM THE REL BLOCK BUFFERS. ; IF A BUFFER IS EMPTY, RDBUF IS CALLED TO SWITCH ; BUFFERS AND FILL THE EMPTY BUFFER. RDBUF: .WAIT 17 ;CHANNEL READY? MOV CURBUF,R0 ;R0 -> BUFFER IN USE MOV (R0)+,RELBUF ;PT TO CURRENT EMPTY BUFR MOV (R0)+,R4 ;SWITCH BUFFER PTS MOV (R0)+,R5 MOV (R0),CURBUF ;INDICATE NEW BUFR IN USE RDBK0: ADDR RLIOBK,R0 ;CURRENT REL BLK TO READ EMT 375 INC RELBLK ;BUMP REL BLOCK PTR BCC 1$ TSTB @#52 ;TEST ERROR BYTE BNE FERR1 ;HARD ERROR EXIT 1$: RTS PC GETWD: CMP R4,R5 ;END OF BUFFER? BLO 1$ ;NO JSR PC,RDBUF ;YES,SWITCH BUFFERS 1$: MOV (R4)+,R2 ;GET A WORD CMP #-2,R2 ;CHECK FOR -1 OR -2 BNE 2$ ;NOT -2 INC FLG2 ;SET -2 FLAG NON-ZERO SEC ;FLAG IT WITH C=1 2$: RTS PC GET2WD: JSR PC,GETWD ;GET A WORD BCS 1$ ;-1 OR -2 EXIT MOV R2,-(SP) ;SAVE TEMP JSR PC,GETWD ;GET 2ND WORD MOV R2,R3 MOV (SP)+,R2 ;FIRST ONE IN R2 1$: RTS PC ; BUFFER POINTERS -- THESE MUST BE KEPT CONTIGUOUS AND IN ; THIS ORDER, BOTH FOR SETUP AND FOR USE BY RDBUF. CURBUF: .WORD 0 ;ADDR OF CURRENT BUFFER PTR BUFR1: .WORD 0 ;ADDR OF THIS BUFFER .WORD 0 ;ADDR OF ALTERNATE BUFR .WORD 0 ;ADDR OF END OF ALT BUFR .WORD 0 ;ADDR OF ALT BUFR TABLE .WORD 0 .WORD 0 .WORD 0 .WORD 0 ; GETBLK -- SUBROUTINE TO SEARCH FREE CORE LIST FOR A BLOCK EQUAL ; TO REQUESTED SIZE. IF NOT IN FREE CORE LIST, KMON/USR IS ; MOVED DOWN TO CREATE THE BLOCK. ; ; CALL SEQUENCE: JSR PC,GETBLK ; R0=# BYTES DESIRED ; ; RETURNS WITH: R4 -> START OF BLOCK+2 ; (R4)-2 = SIZE OF BLOCK (1ST WORD OF BLK) ; ; R1,R3 DESTROYED ; GETBL3: TST (R0)+ ;ADD 2 BYTES TO REQUEST OMOV .CORPT,R3 ;R3 -> FREE CORE LIST HEAD 1$: MOV 2(R3),R4 ;R4 -> NEXT FREE BLOCK OCMP .CORPT,R4 ;END OF LIST? BEQ 4$ ;YES, BACK AT LIST HEAD CMP (R4),R0 ;THIS BLOCK BIG ENOUGH? BGE 2$ ;YES, USE IT. MOV R4,R3 ;NO, TRY NEXT BLOCK BR 1$ 2$: SUB R0,(R4) ;BLK SIZE - REQUEST SIZE BNE 3$ ;EXACTLY THE SAME? MOV 2(R4),2(R3) ;YES, REMOVE FROM LIST 3$: ADD (R4),R4 ;R4 -> START OF BLOCK CLC BR 5$ ;GO EXIT 4$: SUB R0,(SP) ;RELOCATE RETURN ADDR. NEG R0 ;-SIZE => MOVE KMON DOWN ROR R0 ;HALVE IT, C=1 SO IT IS <0 OJSR PC,KUMOVE ;CALL TO MOVE KMON/USR NEG R0 ;FIX R0, SET CARRY 5$: MOV R0,(R4)+ ;STORE SIZE IN FIRST WORD RTS PC ; PUTBLK -- RETURNS A BLOCK OF CORE TO THE FREE CORE LIST. ; MERGES CONTIGUOUS BLOCKS OF CORE INTO A SINGLE BLOCK. ; RECLAIMS CORE FROM BLOCKS CONTIGUOUS TO KMON/USR BY ; SLIDING UP KMON/USR. ; ; CALL SEQUENCE: JSR PC,PUTBLK ; ; R4 -> START OF BLOCK+2 ; (R4)-2 = SIZE OF BLOCK (IN 1ST WORD OF BLK) ; ; R0,R1 DESTROYED ; PUTBL3: TST -(R4) ;POINT TO BLOCK SIZE IN 1ST WD. OMOV .CORPT,R0 ;R0 -> FREE CORE LIST HEAD 1$: MOV 2(R0),R1 ;R1 -> NEXT FREE BLOCK OCMP .CORPT,R1 ;LAST BLOCK IN LIST? BEQ 3$ ;YES, INSERT NEW BLOCK HERE CMP R1,R4 ;NO, NEXT BLOCK HIGHER IN CORE? BHI 2$ ;YES, INSERT BLOCK HERE MOV R1,R0 ;NO, R0 -> CURRENT BLOCK BR 1$ ;CONTINUE SEARCH ; UPPER BOUNDARY CHECK FOR CONTIGUOUS BLOCKS 2$: MOV R4,-(SP) ;COMPUTE ADDR OF END OF ADD (R4),(SP) ;NEW BLOCK OF CORE. CMP (SP)+,R1 ;TOUCHES NEXT BLOCK? BNE 3$ ;NO, CAN'T MERGE ADD (R1)+,(R4)+ ;YES, MERGE THE TWO MOV (R1),(R4) ;BLOCKS INTO ONE. CMP -(R4),-(R1) ;FIX R4,R1 BR 4$ ;THE CHECK LOWER BOUND. 3$: MOV R1,2(R4) ;JUST LINK IN NEW BLK ; LOWER BOUND CHECK FOR CONTIGUOUS BLOCKS 4$: MOV R0,-(SP) ;IS NEW BLOCK CONTIGUOUS ADD (R0),(SP) ;WITH LOWER BLOCK? CMP (SP)+,R4 ;COMPARE BOUNDS BEQ 5$ ;CONTIGUOUS, SO MERGE THEM MOV R4,2(R0) ;NO, JUST LINK TO LOWER BR 6$ ;THEN GO ON 5$: ADD (R4)+,(R0)+ ;ADD SIZES TOGETHER MOV (R4),(R0) ;AND RE-LINK THE LIST. CMP -(R4),-(R0) ;FIX R4,R0 ; CORE RECLAIM CHECK 6$: OMOV .CORPT,R0 ;R0 -> FREE CORE LIST HEAD MOV 2(R0),R1 ;R1 -> LOWEST FREE BLOCK MOV @<.SYSLO-OVLY>-<.+4-OVLYST>(PC),-(SP) CMP (SP)+,R1 ;CONTIGUOUS TO KMON/USR? CLC BNE 7$ ;NO, JUST EXIT BIT (R1)+,(R0)+ ;BUMP R1, R0, LEAVE C=0 MOV (R1),(R0) ;REMOVE FROM LIST MOV -(R1),R0 ;SIZE IN R0 ROR R0 ;HALVE IT, LEAVE > 0 OJSR PC,KUMOVE ;THEN SQUISH IT ADD R0,(SP) ;RELOCATE RETURN ADDRESS SEC 7$: RTS PC ;AND EXIT .ENDC .IF EQ BF .LIST .ENDC .SBTTL GT ON/OFF OVERLAY OVCMD GT MOV @#SYSPTR,R1 ;R1 -> RMON ADD #CONFIG-$RMON,R1 ;R1 -> CONFIG BIT #HWDSP$,(R1)+ ;DISPLAY HARDWARE PRESENT? BEQ BCELNK ;NO, NOTHING WE CAN DO .IF NE BF MOV FCNTXT-SCROLL(R1),R4 ;R4 -> FJOB CONTEXT BEQ 20$ ;ZERO => NO F JOB BIT #NORUN$,@R4 ;FOREGROUND ACTIVE? BEQ BCELNK ;YES, TOO DANGEROUS 20$: .ENDC OADDR DEVSTS,R2 ;R2 -> A BUFFER OJSR PC,GETNAM ;GET RAD50 ARGUMENT CMP (PC)+,@R2 ;TURN DISPLAY ON? .RAD50 /ON / BEQ GTON ;YES CMP (PC)+,@R2 ;TURN DISPLAY OFF? .RAD50 /OFF/ BEQ GTOFF ;YES BCELNK: OJMP BADCOM ; .ENABL LSB GTON: TST @R1 ;SCROLLER ALREADY IN CORE? BNE BCELNK ;YES, CAN'T DO JSR PC,VSTOP ;STOP DISPLAY IF RUNNING ADDR TSTIT,R0 ;R0 -> DISPLAY TEST FILE MOV R0,@#DPC ;RUN IT 2$: MOV @#DSR,R0 ;STOPPED? BPL 2$ ;LOOP UNTIL IT DOES BIT #40,R0 ;EDGE FLAG SET? BEQ 3$ ;NO, 17" SCOPE MOV (PC)+,R3 ;Y POS IN R3 YPS12: .WORD 1350 ;12" SCOPE Y POS DEFAULT MOV (PC)+,R4 ;LINE CT IN R4 LCT12: .WORD 37 ;12" SCOPE LINE CT DEFAULT BR 4$ 3$: MOV (PC)+,R3 ;Y POS IN R3 YPS17: .WORD 1750 ;17" SCOPE Y POS DEFAULT MOV (PC)+,R4 ;LINE CT IN R4 LCT17: .WORD 50 ;17" SCOPE LINE CT DEFAULT 4$: .DSABL LSB .ENABL LSB 1$: TSTB @R5 ;ARE THERE ANY TO PROCESS? BEQ 5$ ;NO 2$: CMPB #'/,@R5 ;SWITCH COMING? BNE BCELNK ;NO,ERROR EXIT MOVB -(R5),R0 ;SAVE SWITCH CMPB #':,-(R5) ;OCTAL VALUE? BEQ 3$ ;YES CMPB #'!,@R5 ;DECIMAL VALUE? BNE BCELNK ;NO, ERROR SEC ;FLAG DECIMAL AND 3$: OJSR PC,CVTNUM ;GO CONVERT VALUE CMPB #'T,R0 ;T SWITCH? BNE 4$ ;NO MOV (SP)+,R3 ;VALUE TO R3 BEQ BCELNK ;ZERO IS ILLEGAL CMP #1777,R3 ;LIMIT TO 1777(8) BLT BCELNK ;TOO BIG BR 1$ ;ANOTHER? 4$: CMPB #'L,R0 ;L SWITCH? BNE BCELNK ;NO, ERROR MOV (SP)+,R4 ;YES, VALUE TO R4 BEQ BCELNK ;ZERO IS ILLEGAL CMP #41.,R4 ;TOO BIG? BLT BCELNK ;YES, ERROR BR 1$ ;ANOTHER SWITCH? 5$: MOV R3,-(SP) ;SAVE Y POS ON STACK MOV R4,-(SP) ;SAVE LINE COUNT MOV #SCRSIZ,R0 ;R0 = SCROLLER SIZE ADD (PC)+,R0 ;PLUS TEXT BUFFER BUFSIZ: .WORD 4000 ;DEFAULT TEXT BUFFER SIZE IN BYTES MOV R1,-(SP) ;SAVE R1 JSR PC,GETBL4 ;ALLOCATE CORE MOV (SP)+,R1 ;RESTORE POINTER BCC 7$ ;KMON/USR MOVED? SUB R0,4(SP) ;YES, RELOCATE RETURN 7$: ; SET UP I/O BLOCK TO READ IN SCROLLER ADDR SCRIOB,R5 ;R5 -> I/O BUFR FOR SCROLLER MOV R4,@R5 ;STORE CORE ADDR MOV #SCRBLK,R0 ;R0 = REL. BLOCK OF SCROLLER ADD @<.$SWPB-OVLY>-<.+4-OVLYST>(PC),R0 ;ADD SWAP BLOCK OFFSET JSR PC,@<.$SYS-OVLY>-<.+4-OVLYST>(PC) ;CALL RMON ROUTINE TO READ BCS 10$ ;READ ERROR MOV BUFSIZ,R0 ;R0 = BUFFER SIZE JMP (R4) ;GO TO INIT ROUTINE 10$: JSR PC,PUTBL4 ;RECOVER CORE OJMP SYIOER ;JUMP TO .DSABL LSB GTOFF: MOV @R1,R4 ;O.K., GET ADDR OF SCRLR BEQ 2$ ;NOT THERE!! JSR PC,VSTOP ;GO STOP DISPLAY ; RESTORE LOCATIONS MODIFIED IN RMON. SPL 7 ;RAISE PRIORITY CLR @R1 ;CLEAR SCROLL PTR. BICB #14,LOWMAP+15-SCROLL(R1) ;CLEAR PROTECT BITS MOV #177600,R2 ;SET UP TO RESTORE CODE .IF NE BF MOV #42700,(R1) ;BIC #,R0 MOV R2,(R1) ;#177600 .IFF MOV #42700,(R1) ;BIC #,R0 MOV R2,(R1) ;#177600 MOV #42704,(R1) ;BIC #,R4 MOV R2,(R1) ;177600 .ENDC MOV (R4),(R1) MOV (R4),(R1) SPL 0 ;LOWER PRIORITY JSR PC,PUTBL4 ;RECOVER CORE BCC 2$ ;KMON/USR MOVED? ADD R0,(SP) ;YES, RELOC RETURN 2$: RTS PC ; SUBROUTINE TO STOP THE DISPLAY DPC=172000 ;DISPLAY PROGRAM COUNTER DSR=172002 ;DISPLAY STATUS REGISTER VSTOP: ADDR STPIT,R2 ;R2 -> DISPLAY FILE 1$: MOV R2,@#DPC ;MOVE IT TO DISPLAY PC TST @#DSR ;STOPPED? BPL 1$ ;NO, DO IT AGAIN RTS PC ;YES, IT'S STOPPED! TSTIT: 114000 ;POINT MODE 0 1350 104000 ;SHORTV MODE 77 STPIT: 173000 ;STOP DISPLAY W/O INT. ; THIS IS THE I/O TABLE THAT DRIVES THE LOADING OF THE SCROLLER SCRIOB: .WORD 0 ;CORE ADDRESS TO LOAD SCROLLER .WORD SCRTOT ;SCROLLER SIZE IN WORDS .WORD 0 ;WAIT I/O ; GETBLK -- SUBROUTINE TO SEARCH FREE CORE LIST FOR A BLOCK EQUAL ; TO REQUESTED SIZE. IF NOT IN FREE CORE LIST, KMON/USR IS ; MOVED DOWN TO CREATE THE BLOCK. ; ; CALL SEQUENCE: JSR PC,GETBLK ; R0=# BYTES DESIRED ; ; RETURNS WITH: R4 -> START OF BLOCK+2 ; (R4)-2 = SIZE OF BLOCK (1ST WORD OF BLK) ; ; R1,R3 DESTROYED ; GETBL4: TST (R0)+ ;ADD 2 BYTES TO REQUEST OMOV .CORPT,R3 ;R3 -> FREE CORE LIST HEAD 1$: MOV 2(R3),R4 ;R4 -> NEXT FREE BLOCK OCMP .CORPT,R4 ;END OF LIST? BEQ 4$ ;YES, BACK AT LIST HEAD CMP (R4),R0 ;THIS BLOCK BIG ENOUGH? BGE 2$ ;YES, USE IT. MOV R4,R3 ;NO, TRY NEXT BLOCK BR 1$ 2$: SUB R0,(R4) ;BLK SIZE - REQUEST SIZE BNE 3$ ;EXACTLY THE SAME? MOV 2(R4),2(R3) ;YES, REMOVE FROM LIST 3$: ADD (R4),R4 ;R4 -> START OF BLOCK CLC BR 5$ ;GO EXIT 4$: SUB R0,(SP) ;RELOCATE RETURN ADDR. NEG R0 ;-SIZE => MOVE KMON DOWN ROR R0 ;HALVE IT, C=1 SO IT IS <0 OJSR PC,KUMOVE ;CALL TO MOVE KMON/USR NEG R0 ;FIX R0, SET CARRY 5$: MOV R0,(R4)+ ;STORE SIZE IN FIRST WORD RTS PC ; PUTBLK -- RETURNS A BLOCK OF CORE TO THE FREE CORE LIST. ; MERGES CONTIGUOUS BLOCKS OF CORE INTO A SINGLE BLOCK. ; RECLAIMS CORE FROM BLOCKS CONTIGUOUS TO KMON/USR BY ; SLIDING UP KMON/USR. ; ; CALL SEQUENCE: JSR PC,PUTBLK ; ; R4 -> START OF BLOCK+2 ; (R4)-2 = SIZE OF BLOCK (IN 1ST WORD OF BLK) ; ; R0,R1 DESTROYED ; PUTBL4: TST -(R4) ;POINT TO BLOCK SIZE IN 1ST WD. OMOV .CORPT,R0 ;R0 -> FREE CORE LIST HEAD 1$: MOV 2(R0),R1 ;R1 -> NEXT FREE BLOCK OCMP .CORPT,R1 ;LAST BLOCK IN LIST? BEQ 3$ ;YES, INSERT NEW BLOCK HERE CMP R1,R4 ;NO, NEXT BLOCK HIGHER IN CORE? BHI 2$ ;YES, INSERT BLOCK HERE MOV R1,R0 ;NO, R0 -> CURRENT BLOCK BR 1$ ;CONTINUE SEARCH ; UPPER BOUNDARY CHECK FOR CONTIGUOUS BLOCKS 2$: MOV R4,-(SP) ;COMPUTE ADDR OF END OF ADD (R4),(SP) ;NEW BLOCK OF CORE. CMP (SP)+,R1 ;TOUCHES NEXT BLOCK? BNE 3$ ;NO, CAN'T MERGE ADD (R1)+,(R4)+ ;YES, MERGE THE TWO MOV (R1),(R4) ;BLOCKS INTO ONE. CMP -(R4),-(R1) ;FIX R4,R1 BR 4$ ;THE CHECK LOWER BOUND. 3$: MOV R1,2(R4) ;JUST LINK IN NEW BLK ; LOWER BOUND CHECK FOR CONTIGUOUS BLOCKS 4$: MOV R0,-(SP) ;IS NEW BLOCK CONTIGUOUS ADD (R0),(SP) ;WITH LOWER BLOCK? CMP (SP)+,R4 ;COMPARE BOUNDS BEQ 5$ ;CONTIGUOUS, SO MERGE THEM MOV R4,2(R0) ;NO, JUST LINK TO LOWER BR 6$ ;THEN GO ON 5$: ADD (R4)+,(R0)+ ;ADD SIZES TOGETHER MOV (R4),(R0) ;AND RE-LINK THE LIST. CMP -(R4),-(R0) ;FIX R4,R0 ; CORE RECLAIM CHECK 6$: OMOV .CORPT,R0 ;R0 -> FREE CORE LIST HEAD MOV 2(R0),R1 ;R1 -> LOWEST FREE BLOCK MOV @<.SYSLO-OVLY>-<.+4-OVLYST>(PC),-(SP) CMP (SP)+,R1 ;CONTIGUOUS TO KMON/USR? CLC BNE 7$ ;NO, JUST EXIT BIT (R1)+,(R0)+ ;BUMP R1, R0, LEAVE C=0 MOV (R1),(R0) ;REMOVE FROM LIST MOV -(R1),R0 ;SIZE IN R0 ROR R0 ;HALVE IT, LEAVE > 0 OJSR PC,KUMOVE ;THEN SQUISH IT ADD R0,(SP) ;RELOCATE RETURN ADDRESS SEC 7$: RTS PC ;AND EXIT .SBTTL SET COMMAND .IF EQ BF ;THIS CONDITION RUNS OVER THE WHOLE COMMAND OVERLAY .IFTF OVCMD SET MOV @#SYSPTR,R0 ;POINT TO RESIDENT .IFF ;F/B MOV TTCNFG-$RMON(R0),SET58$ ;GET OLD CONFIG MOVB TTWIDTH-$RMON(R0),SET59$ ;GET OLD WIDTH .IFTF ;BOTH ADDR SET60$,R4 ;POINT R4 TO TTY STUFF HERE MOV CONFIG-$RMON(R0),R2 ;GET OLD CONFIG WORD BIC #^C,R2 ;ISOLATE OLD VALUE OF USR$ MOV R2,SET62$ ;SAVE IT JSR PC,SET90$ ;GET A HANDLER NAME JSR R4,SET98$ ;SKIP OVER COLON, IF ANY .WORD ': TST 2(R2) ;HANDLER NAMES ARE 1 WORD BNE SET42$ ;INVALID CMP @R2,(PC)+ ;IS IT 'SET USR'? .RAD50 /USR/ BEQ 1$ ;YES, NO READS OR WRITES ADD #SET50$-SET60$,R4 ;POINT TO TTY PARAMETERS CMP @R2,(PC)+ ;TTY IS SPECIAL .RAD50 /TTY/ BEQ 1$ ;USE THE LOCAL STUFF MOV (PC)+,-(R2) ;THE HANDLER IS ON SY: .RAD50 /SY / MOV #75273,6(R2) ;THIS IS .RAD50 /SYS/, THE EXTENSION MOV #3*400+17,R0 ;PURGE CHANNEL 17 EMT 374 .LOOKU 17,R2 ;LOOK UP THE HANDLER BCS SET40$ ;IT AIN'T THERE OMOV .USRBUF,R4 ;POINT TO USR BUFFER CLR @<.BLKEY-OVLY>-<.+4-OVLYST>(PC) ;WE CLOBBER DIRECTORY CLR R0 ;READ BLOCK 0 .READW 17,R4,#512. ;READ 1ST 2 BLOCKS INTO USR BUFFER BCS SET41$ ;SY I/O ERROR ADD #400,R4 ;R4 -> COMMAND TABLE 1$: MOVB -(R5),R0 ;ASSEMBLE 2 CHARACTERS TO CHECK FOR 'NO' SWAB R0 CLRB R0 BISB -(R5),R0 SUB #"ON,R0 ;CHECK FOR 'NO', LEAVE R0=0 IF 'NO' BEQ 11$ ;GO FIX FOR 'NO' CMPB (R5)+,(R5)+ ;FIX R5, WE GOT NO 'NO' BR 2$ 11$: JSR PC,SET96$ ;SKIP BLANKS AFTER 'NO', IF ANY 2$: JSR PC,SET90$ ;GET THE OPTION NAME MOV R4,R1 ;POINT TO OPTION TABLE BR 5$ ;ENTER LOOP 3$: TST (R1)+ ;SKIP 2ND WORD OF OPTION NAME 4$: CMP (R1)+,-(R2) ;SKIP FLAGS, FIX R2 5$: MOV (R1)+,R3 ;GET PRESET WORD BEQ SET42$ ;0 => END OF TABLE, ERROR CMP (R2)+,(R1)+ ;CHECK 1ST WORD OF NAME BNE 3$ ;NO CMP @R2,(R1)+ ;2ND WORD BNE 4$ ;NOT YET MOV R4,R2 ;COPY ENTRY POINTER MOV @R1,R1 ;R1 = FLAGS, OFFSET BMI 6$ ;'NO' IS ALLOWED TST R0 ;'NO' IS ILLEGAL. WAS IT GIVEN? BEQ SET42$ ;YES, ERROR 6$: TST R0 ;'NO' GIVEN? BNE 7$ ;NO CMP (R2)+,(R2)+ ;YES, ALTER ENTRY POINT 7$: ASL R1 ;DOUBLE OFFSET BPL 8$ ;NO NUMBER REQUIRED JSR R4,SET98$ ;NUMBER NEEDED. SKIP OVER OPTIONAL '=' .WORD '= BIC #100000,R1 ;FIX R1 MOV R5,R0 ;COPY LINE POINTER DEC R0 OJSR PC,DECNUM ;CALL NUMBER GETTER CMP R5,R0 ;DID THE POINTER MOVE? BEQ SET42$ ;NO NUMBER = ERROR MOV (SP)+,R0 ;GET NUMBER IN R0 JSR PC,SET95$ ;SKIP OVER BLANKS, IF ANY 8$: ADD R1,R2 ;ADDRESS OF ROUTINE IN R2 (CLEAR CARRY) JSR PC,@R2 ;CALL PARAMETER ROUTINE BCS SET42$ ;HANDLER DETECTED ERROR TSTB -1(R5) ;END OF LINE? BEQ SET10$ ;YES, CLOSE IT OUT JSR R4,SET98$ ;NO, SKIP OPTIONAL , .WORD ', BR 1$ ;LOOP SET10$: OCMP .USRBUF,R4 ;WAS THIS THE TTY OR USR? BHI SET45$ ;YES, IT WAS IN THE KMON OMOV .USRBUF,R4 ;REPOINT TO BUFFER CLR R0 ;WRITE BLOCK 0 .WRITW 17,R4,#512. ;REWRITE THE HANDLER BCS SET41$ ;ERROR (THIS IS A REALLY BAD ONE) RTS PC ;BACK TO THE SHADOWS AGAIN SET40$: OJMP BADHAN SET41$: OJMP SYIOER SET42$: OJMP BADCOM SET45$: MOV @#SYSPTR,R0 ;SET TTY OR SET USR. POINT TO RMON BIC #USR$,CONFIG-$RMON(R0) ;TURN OFF OLD VALUE OF USR$ BIS SET62$,CONFIG-$RMON(R0) ;AND PUT IN NEW VALUE .IFF ;F/B MOV SET58$,TTCNFG-$RMON(R0) ;PUT IN NEW TTY CONFIG MOVB SET59$,TTWIDT-$RMON(R0) ;AND NEW WIDTH ADD #LISTFB-$RMON,R0 ;POINT TO WORDS FOR F/B SWITCH MOV #100000,R1 ;THIS FLAG SETS OR CLEARS BIT #FBTTY$,SET58$ ;ON OR OFF? BNE 1$ ;ON BIS R1,(R0)+ ;OFF. TURN ON BIT SO IT NEVER MATCHES BIS R1,(R0)+ RTS PC 1$: BIC R1,(R0)+ BIC R1,(R0)+ .IFTF RTS PC SET60$: .WORD USR$ .RAD50 /SWAP / .WORD /2+100000 0 SET61$: CLR R3 ;SET USR$ OFF FOR 'SWAP' NOP MOV R3,(PC)+ SET62$: 0 RTS PC SET50$: .IFF ;F/B .WORD HWTAB$ .RAD50 /TAB / .WORD /2+100000 .WORD VT05$ .RAD50 /SCOPE / .WORD /2+100000 .WORD FORM$ .RAD50 /FORM / .WORD /2+100000 .WORD CRLF$ .RAD50 /CRLF / .WORD /2+100000 .WORD PAGE$ .RAD50 /PAGE / .WORD /2+100000 .WORD 30. .RAD50 /WIDTH / .WORD /2+40000 .WORD FBTTY$ .RAD50 /FB / .WORD /2+100000 .IFTF .WORD '_ ;DISABLE VT50 PRINT .RAD50 /COPY / .WORD /2+100000 .WORD '\ ;DISABLE SCREEN HOLD .RAD50 /HOLD / .WORD /2+100000 0 .IFF ;F/B SET51$: BR SET53$ 0 SET52$: BIC R3,(PC)+ SET58$: 0 RTS PC SET53$: BIS R3,SET58$ RTS PC SET54$: MOVB R0,(PC)+ SET59$: 0 CMPB R0,R3 RTS PC .IFTF ;BOTH ; THIS CODE SUPPORTS THE VT50 HOLD AND HARD COPY OPTIONS. ; IT TRANSMITS THE PROPER ESCAPE SEQUENCE TO THE TERMINAL, ; TOGGLING THE LOGIC EACH TIME THE SEQUENCE IS SENT. THE HOLD ; OPTION PUTS THE VT50 IN AUTO-PAGE MODE. THE COPY OPTION TURNS ; THE HARD-COPY UNIT ON AND OFF. SET70$: DEC R3 ;TURN THE OPTION ON NOP ;'NO' ENTRY POINT MOVB R3,ESCLOC ;INSERT ESCAPE CHARACTER ADDR ESCSEQ,R0 ;POINT TO STRING .PRINT ;AND OUTPUT IT RTS PC ESCSEQ: .BYTE 33 ESCLOC: .BYTE 0 .BYTE 0 .EVEN SET90$: OADDR DEVSTS+2,R2 ;POINT TO A HANDY BLOCK MOV R0,-(SP) ;SAVE R0 OJSR PC,GETNAM ;GET 2 WORDS OF RAD50 BEQ SET42$ ;ERROR MOV (SP)+,R0 ;RESTORE R0 SET95$: INC R5 ;START SCAN FOR NON-BLANK SET96$: CMPB -(R5),#40 ;BLANK? BEQ SET96$ ;YES, KEEP GOING INC R5 ;NO, BACK UP RTS PC SET98$: CMPB (R4)+,-(R5) ;ARE WE POINTING TO THE OPTIONAL BYTE? BNE SET100 ;NO SET99$: CMPB -(R5),#40 ;YES, SKIP OPTIONAL AND BLANKS BEQ SET99$ SET100: CMPB (R4)+,(R5)+ ;FIX R4 AND R5 RTS R4 ;OUT .ENDC ;.IF EQ BF .SBTTL VT11 SHIFT OUT INTERRUPT SERVICE OVERLAY SCRBLK=OVLYN+RT11SZ+SWAPSZ ;BLOCK # OF SCROLLER ; THIS OVERLAY BLOCK SHOULD FOLLOW THE GT OVERLAY ; AND BE THE LAST BLOCK IN THE OVERLAY FILE. ; THIS INTERRUPT HANDLER SERVICES THE SCROLL BUFFER ; DURING VT11 SUPPORT OF THE RT11 MONITOR. THE SHIFT OUT ; INTERRUPT WITH A CHARACTER CODE OF 77 IS USED TO ; INDICATE END OF SCREEN. IT PROVIDES A PERIODIC INTERRUPT ; FOR SERVICING THE SCROLLER. SINCE THE INTERRUPT IS REQUIRED ; TO REMOVE CHARACTERS FROM THE OUTPUT RING BUFFER, IT IS ; IMPORTANT THAT THE DPU BE RUNNING. THE USER WHO LINKS TO ; THE SCROLL FILE AND STOPS THE DPU FOR LONG PERIODS OF TIME ; WHILE USING TTY OUTPUT RISKS HANGING RT11. SCBGIN=. ; THE FOLLOWING SIX WORDS, SCTPS THRU SCTC, MUST BE FIRST ; AND THEIR ORDER SHOULD NOT BE CHANGED. SCTPS: .WORD 0 ;SET TO 100 TO INDICATE CHAR. READY SCTPB: .WORD 0 ;OUTPUT CHAR. FROM TTOINT IN RMON SCMAX: .WORD 0 ;MAX. LINES OF SCROLLING SCLINK: DJMP ;SCROLLER LINK FILE FOR USER LINKS SCTOP-SCTPS SCTC: .WORD SCTRLC-SCTPS ;ADDRESS OF CTRL/C ROUTINE SCECHO: .BYTE 1 ;TTY ECHO FLAG(1 DON'T; -1 DO) SCTTF: .BYTE 0 ;TT WAIT FLAG SCSTOP: SCHEAD-2-SCTPS ;PTR TO STOP CODE SCHDP: .WORD SCHEAD-SCTPS ;POINTER TO HEADER SCCHMX: .WORD 0 ;MAX. CHAR. COUNT SCMCNT: .WORD 0 ;MASTER LINE COUNT SCADVF: .BYTE 0 ;PAGE ADVANCE FLAG(1=WAIT, 0=GO) SCLOCK: .BYTE 0 ;SCROLL LOCK FLAG(0 UNLOCK;NON-0 LOCK) SCPSSV: .WORD 0 ;SAVE AREA FOR TTPS CONTENTS SCPBSV: .WORD 0 ;SAVE AREA FOR TTPB CONTENTS $SCINT: MOV @#SYSPTR,-(SP) JSR R5,@(SP)+ ;GO TO SYSTEM STATE .WORD ^C&PR7 ;AT PRIORITY 4 MOV R3,-(SP) MOV SCTPB,R3 ;RESTORE R3 FOR ECHO SC1MOR: MOV SCTRLR,R5 ;POINT TO LAST CHAR. TSTB SCTTF ;TT ECHO IN PROGRESS? BNE 8$ ;YES TSTB SCADVF ;PAGE FULL? BNE SCRESM ;YES, RESUME DISPLAY CLR @SCPSSV ;CLEAR ANY INTR. TST SCTPS ;CHAR TO BE ADDED? BEQ SCRESM ;JUST EXIT 1$: TST SCTPB ;SOMETHING THERE? BNE 2$ ;YES, GO ON MOV @#PS,-(SP) ;SIMUL. AN INTER. MOV @#64,R4 ;GET ADDR. IN TRAP JSR PC,(R4) ;CALL PRINTER ROUTINE 2$: MOV SCTPB,R3 ;CHAR TO R3 .IF NE BF ;F/B ONLY CMP #10,R3 ;BACK SPACE? BNE 4$ ;NO DEC R5 ;POINT TO PREV. CHAR CMP R5,SCBUFS ;WRAP AROUND? BHIS 3$ ;NO, O.K. MOV SCBUFE,R5 ;YES, WRAP TO END 3$: CMPB #12,@R5 ;BUT DON'T BACK SPACE BEQ 5$ ;OVER A LINE FEED DEC SCCHCT ;DECREASE COUNT CLR R3 ;CLEAR THE RUBOUT CLR SCTPB CLRB @R5 ;CLEAR CHAR IN SCROLL BR SCTRLR-2 ;GO NULL IT OUT .IFTF ;S/J OR F/B 4$: CMPB #16,R3 ;SHIFT OUT CODE? BNE 6$ ;NO, GO ON 5$: CLR R3 ;YES, NULL IT OUT 6$: CMPB #7,R3 ;IS IT A BELL? BEQ 7$ ;YES, FORCE AN ECHO TSTB SCECHO ;SHOULD WE ECHO? BPL 10$ ;NO, SCROLL ONLY 7$: INCB SCTTF ;SET TT WAIT FLAG 8$: TSTB @SCPSSV ;TTY BUSY? BEQ SCRESM ;YES, EXIT FOR NOW CLRB SCTTF ;CLEAR WAIT FLAG MOV R3,@SCPBSV ;SEND TO PRINTER 10$: CLR SCTPB ;THEN CLEAR BUFFER TST R3 ;IS IT A NULL? BEQ SCRESM ;YES, SKIP ALL THIS JSR PC,SCNSRT ;NO, INSERT INTO SCROLL .ENABL LSB .IFF ;S/J ONLY CMPB #CR,R3 ;IS IT A CARRIAGE RETURN? BNE 1$ ;NO CLR SC72CT ;CLEAR CHAR COUNT, NEW LINE 1$: .IFTF ;S/J OR F/B CMPB #LF,R3 ;LINE FEED? BNE 2$ ;NO JSR PC,SCPACK ;PACK LF WITH NULL? 2$: .IFF ;S/J ONLY ; TEST NUMBER OF CHARACTERS IN THIS LINE AND GENERATE A CR/LF ; IF THEY EXCEED 72. THEN RESET CHAR. COUNT FOR A NEW LINE. CMP #72.,SC72CT ;FULL LINE? BGT 5$ ;NO, GO ON MOV (PC)+,R3 ;YES, INSERT A CR .BYTE CR,LF JSR PC,SCNSRT SWAB R3 ;THEN A LF JSR PC,SCNSRT JSR PC,SCPACK ;PACK WORD WITH NULL? CLR SC72CT ;CLEAR CHARACTER COUNT 5$: .IFTF ;S/J OR F/B MOV R5,(PC)+ ;THEN SAVE THE SCTRLR: .WORD SCBUFR-SCTPS ;PTR TO LAST CHARACTER CLRB (R5)+ ;PUT A NULL AFTER LAST CHAR. ;EVEN IT SO STOP BIC #1,R5 ;CODE FITS ON WORD BOUND JSR PC,SCWRAP ;WRAP AROUND? MOV #SOCODE,(R5) ;INSERT STOP CODE TST SCLF ;WAS IT A LF? BEQ SC1MOR ;NO, GET ANOTHER CHAR. CLR SCLF ;YES, CLEAR THE FLAG SCRESM: MOV (SP)+,R3 SCSTRT: MOV SCHDP,@#DPC ;START DISPLAY RTS PC .DSABL LSB ; SUBROUTINE TO INSERT A SINGLE CHARACTER INTO THE SCROLL BUFFER. ; TESTS FOR BUFFER FULL AND DELETES A LINE IF NECESSARY. ALSO ; CHECKS FOR WRAP AROUND. CHARACTER IN R3, BUFFER PTR. IN R5. .ENABL LSB SCNSRT: MOVB R3,(R5)+ ;MOVE CHAR TO BUFR INC (PC)+ ;BUMP CHAR COUNT SCCHCT: .WORD 0 ;CURRENT CHARACTER COUNT .IFF ;S/J ONLY CMPB R3,#40 ;IS IT PRINTING CHAR? BLT 1$ ;NO INC (PC)+ ;BUMP THE CURRENT SC72CT: .WORD 0 ;LINE CHARACTER COUNT .IFTF ;S/J OR F/B 1$: CMP SCCHCT,SCCHMX ;FULL? BLT 3$ ;NO TST SCLNCT ;YES, BUT IS THERE A LINE? BNE 2$ ;YES, GO AHEAD MOVB #LF,-(R5) ;NO LINE, SO CREATE ONE INC SCLNCT 2$: JSR PC,SCDEL ;DELETE A LINE 3$: JSR PC,SCWRAP ;CHECK FOR WRAP AROUND RTS PC .DSABL LSB .ENDC ; SUBROUTINE TO PROCESS LINE FEEDS. THE LINE COUNT IS INCREMENTED ; AND THE LINE FEED FLAG IS SET TO TERMINATE INPUT FOR THIS ; INTERRUPT. IF THE LF WAS INSERTED ON AN EVEN BYTE, A NULL ; IS PACKED INTO THE ODD BYTE SO THE NEXT LINE WILL START ON AN ; EVEN BYTE, AN ASSUMPTION MADE IN SCDEL. SCPACK: INC (PC)+ ;SET THE LF FLAG SCLF: .WORD 0 ;LINE FEED RECEIVED FLAG INC (PC)+ ;BUMP THE LINE COUNT SCLNCT: .WORD 0 ;CURRENT LINE COUNT CLR R3 BIT #1,R5 ;ODD BYTE? BEQ 2$ ;NO, GO ON JSR PC,SCNSRT ;YES, PACK WITH A NULL 2$: CMP SCLNCT,SCMAX ;TOO MANY LINES? BLT 3$ ;NO JSR PC,SCDEL ;YES,DELETE ONE BR 2$ 3$: RTS PC ; SUBROUTINE TO CHECK FOR WRAP AROUND. R5 IS POINTING TO SCROLL BUFFER. ; RESET R5 TO TOP OF SCROLL BUFFER IF NECESSARY. .ENABL LSB SCWRAP: CMP R5,SCBUFE ;END OF BUFFER? BLO 1$ MOV (PC)+,R5 ;YES, RESET R5 TO TOP SCBUFS: .WORD SCBUFR-SCTPS ;PTR TO START OF BUFFER 1$: RTS PC .DSABL LSB ; DELETE A LINE - R4 POINTS TO START OF FIRST LINE OF SCROLL DISPLAY. ; LINES ARE DELETED FROM THE TOP OF THE DISPLAY. .ENABL LSB SCDEL: MOV SCPNTR,R4 ;POINT TO FIRST LINE 1$: MOVB @R4,-(SP) ;GET A CHARACTER DEC SCCHCT ;DEC. CHAR COUNT JSR PC,SCCLR ;CLEAR OUT A CHAR. CMPB #LF,(SP)+ ;END OF LINE? =LF BNE 1$ ;NO, CLEAR ANOTHER DEC SCLNCT ;DECR. LINE COUNT BIT #1,R4 ;WAS LF ON EVEN BYTE? BEQ 2$ ;NO DEC SCCHCT ;YES,BUMP OVER NULL IN ODD BYTE INC R4 ;AND UPDATE POINTER 2$: MOV R4,SCPNTR ;RESET POINTER TSTB SCLOCK ;SCROLL LOCK IN EFFECT? BEQ 5$ ;NO INC (PC)+ ;INC. PAGE LINE COUNT SCPGCT: .WORD 1 ;PAGE LINE COUNT (INIT TO 1) CMP SCPGCT,SCMAX ;FILLED THE PAGE YET? BLT 5$ ;NO, O.K. INCB SCADVF ;YES, SET FLAG TO LOCK IT 5$: RTS PC .DSABL LSB ; SUBROUTINE TO CLEAR A CHARACTER AND CHANGE COUNT. SCCLR: CLRB (R4)+ ;CLEAR THE CHARACTER CMP R4,(PC)+ ;WRAP AROUND? SCBUFE: .WORD 0 ;PTR TO END OF BUFFER BLO 1$ ;NO MOV SCBUFS,R4 ;YES 1$: RTS PC .SBTTL CONTROL CHARACTER INTERCEPT ROUTINE ; ; THIS ROUTINE INTERCEPTS CONTROL CHARACTERS IN THE RT11 RMON ; TTY HANDLER BEFORE THEY ARE CONVERTED TO PRINTING FORMAT ; (^ CHAR.). CONTROL CHARACTERS USED BY THE SCROLLER ARE ; ACTED UPON BEFORE CONTROL IS RETURNED TO THE MONITOR. ; CONTROL C CAUSES RESTORATION OF THE SCROLL BUFFER TO THE ; DPU LOOP AND RESTORES THE SHIFT OUT INTERRUPT TRAP ADDR. ; ; THE OTHER CONTROL CHARACTERS HAVE THE FOLLOWING FUNCTIONS: ; ; CTRL A ADVANCE THE SCROLL A PAGE, IF LOCKED ; CTRL Q CLEAR THE SCROLL LOCK FLAG ; CTRL S SET THE SCROLL LOCK FLAG ; CTRL E TOGGLE THE TTY PRINTER ECHO FLAG ; THE BIC INSTRUCTION MUST HAVE THE TAG SCEXAM! .ENABL LSB SCEXAM: BIC #177600,R0 ;THIS INSTRUCTION MUST BE HERE .IF NE BF MOV @#30,-(SP) ;CHECK FOR PAGE MODE SUB #2,@SP TSTB @(SP)+ ;IS IT ON? BPL 99$ ;NO, SKIP THIS .ENDC CMP #'A-100,R0 ;CONTROL A? BEQ 3$ CMP #'Q-100,R0 ;CONTROL Q? BEQ 2$ CMP #'S-100,R0 ;CONTROL S? BEQ 4$ 99$: CMP #'C-100,R0 ;CONTROL C? BEQ 1$ CMP #'E-100,R0 ;CONTROL E? BNE 7$ ;NONE, JUST RETURN NEGB SCECHO ;TOGGLE ECHO FLAG BR 6$ ;THEN EXIT 1$: JSR PC,SCDSTP ;STOP DISPLAY FIRST CLR SCADVF ;PAGE ADVANCE FLAGS .IF EQ BF JSR PC,SCTRLC ;CALL CTRL/C CODE .IFF JSR PC,SCSTRT ;START THE DISPLAY .ENDC 7$: TST R0 ;SET UP TO RETURN RTS PC 2$: CLRB SCLOCK ;CLEAR SCROLL LOCK FLAG 3$: MOV #1,SCPGCT ;RESET PAGE LINE COUNT CLR R0 ;CLEAR ADVANCE FLAG BR 5$ 4$: MOVB R0,SCLOCK ;SET THE LOCK FLAG NON-0 5$: MOVB R0,SCADVF ;LOCK THE PAGE 6$: CLR R0 ;CHANGE TO NULL RTS PC .DSABL LSB ; CTRL/C ROUTINE TO UNLINK ANY USER FILE AND CLEAR THE VECTORS SCTRLC: MOV #SCTOP-SCTPS,SCLINK+2 ;RESTORE SCROLL MOV SCMCNT,SCMAX ;RESTORE LINE COUNT MOV R1,-(SP) MOV @#54,R1 ;POINT TO RMON BIC #GTLNK$,(R1) ;CLEAR USER LINK BIT MOV (R1),R1 ;R1 = VT11 VECTOR CLR (R1)+ CLR (R1)+ CLR (R1)+ CLR (R1)+ MOV (PC)+,(R1)+ ;SET UP VECTOR SCILOC: .WORD $SCINT-SCTPS ;ADDR OF INT. HANDLER MOV (PC)+,@R1 ;SET UP PRIORITY .WORD PR7 ;DISPLAY PRIORITY MOV (SP)+,R1 SCSLNK: JMP SCSTRT ;GO START DISPLAY ; SUBROUTINE TO STOP A VT11 DISPLAY PROCESSOR SCDSUP: MOV SCSTOP,@#DPC ;STOP THE DISPLAY SCDSTP: BIT #100100,@#DSR ;IS DISPLAY STOPPED? BEQ SCDSUP ;NO, MUST BE RUNNING RTS PC ; SUBROUTINE CALLED FROM TTOPUT IN RMON. IT INSURES ; THE DISPLAY IS STARTED AGAIN IF IT WAS ZAPPED BY A ; HARDWARE RESET FROM SOME CUSP. ; .IF EQ BF SCSTIT: BIC #177600,R4 ;DO INSTR THAT WAS OVRLYED TST @#DPC ;DISPLAY ZAPPED BY RESET? BEQ SCSLNK ;YES, GO START IT RTS PC ;RETURN TO MONITOR .ENDC .SBTTL HEAD OF SCROLL BUFFER ; THIS IS THE ACTUAL SCROLL BUFFER. THE HEADER AND ALL ; POINTERS ARE POSITIONED JUST BEHIND THE SCROLLER CODE ; TO FACILITATE RELOCATION ALONG WITH THE SCROLLER CODE, INDEPEN- ; DENT OF BUFFER SIZE. ONLY A FINAL DJMP TO BUFFER TOP IS REQUIRED ; AT BUFFER END. ; DISPLAY PROCESSOR MNEMONICS DNOP=164000 DSTOP=173400 DJMP=160000 CHAR=100000 POINT=114000 INT4=3000 LPOFF=100 BLKON=30 BLKOFF=20 SOCODE=77416 ;SHIFT OUT!177 JSRABS=004737 ;JSR (MODE 3) ; SCROLL HEADER 173000 ;STOP THE DISPLAY SCHEAD: CHAR!BLKON ;CHAR MODE!BLINKING .WORD 77417 ;SHIFT IN, THEN CURSOR POINT!BLKOFF!LPOFF!INT4 ;RESET CONDITIONS .WORD 0 SCYPS: .WORD 0 ;AND POSITION BEAM DJMP SCLINK-SCTPS ;JUMP TO LINK SEGMENT SCTOP: CHAR!BLKOFF!LPOFF ;RETURN HERE AND PREPARE .WORD 171040 ;INITIALIZE DISPLAY DJMP ;TO DISPLAY THE BUFFER. SCPNTR: .WORD SCBUFR-SCTPS ;JUMP TO FIRST LINE. SCBUFR: .WORD SOCODE ;END OF SCROLL ; ALL OF THE CODE THAT FOLLOWS IS ONE-TIME INITIALIZATION ; CODE THAT IS PLACED IN THE SCROLL BUFFER. IT WILL BE ; OVERLAYED WITH CHARACTERS ONCE THE SCROLLER STARTS. ; ASSUMES: R1 -> SCROLL WORD IN RMON (SCROLL) ; R4 -> BEGINNING OF SCROLL LOGIC (SCTPS) ; R0 = BUFFER SIZE ; DESTROYS: R0,R2,R3,R4 .MACRO RELOC TAG ADD R4,TAG .ENDM SCINIT: MOV (SP)+,(R4) ;SET UP LINE COUNT MOV (SP)+,(R4) ;AND Y POS MOV R4,@R1 ;STORE PTR TO SCROLLER MOV R0,(R4) ;AND BUFR SIZE RELOC SCTC RELOC SCLINK+2 RELOC SCTRLR RELOC SCBUFS RELOC SCPNTR RELOC SCSTOP RELOC SCHDP RELOC SCYPS+4 RELOC SCILOC RELOC SCTRLC+2 MOV SCPNTR,R3 ;POINT TO BUFFER ADD SCCHMX,R3 ;ADJUST TO END SUB #2,SCCHMX ;REDUCE CNT FOR STOP CODE MOV R3,SCBUFE ;STORE IT MOV #DJMP,(R3)+ ;THEN INSERT FINAL DJMP MOV SCPNTR,(R3)+ ;TO TOP OF BUFFER MOV @#SYSPTR,R0 ;NOW POINT TO RMON MOV #PR4,@#PS ;RAISE PRIORITY .IF EQ BF ;S/U MOV R4,R3 ADD #SCSTIT-SCTPS,R3 ;POINT TO SCSTIT MOV #TTSCRL-$RMON,R2 ;POINT TO TTSCRL ADD R0,R2 ;RELOCATE IT MOV #JSRABS,(R2)+ ;OVERLAY TTSCRL WITH MOV R3,(R2) ;JSR TO SCSTIT .IFTF ;BOTH MOV R4,R3 ADD #SCEXAM-SCTPS,R3 ;POINT TO SCEXAM MOV R0,R2 .IFF ;F/B ADD #TTIINT+16-$RMON,R2 ;POINT TO LOC. IN RMON .IFT ;S/U ADD #TTIINT+22-$RMON,R2 .ENDC MOV #JSRABS,(R2)+ ;OVERLAY WITH JSR MOV R3,(R2) ;TO SCEXAM MOV (R1),SCPSSV ;SAVE CONTENTS MOV R4,(R1) ;DIVERT CHARS. TO SCROLLER TST (R4)+ MOV (R1),SCPBSV ;SAVE CONTENTS MOV R4,(R1) MOV (R1),R2 ;R2 -> VT11 VECTOR ADD #10,R2 ;ADJUST TO SHIFT OUT VECTOR MOV #1,R4 ;PROTECT TWO BITS MOV R1,R0 ;POINT R0 T0 THE ADD #LOWMAP-SCROLL,R0 ;PROTECT BIT MAP MOV (R1),R1 ;R1 -> KMON JSR PC,(R1) ;GO SET THE BITS JSR PC,SCTRLC ;START THE DISPLAY JSR PC,SCSTRT CLR @#PS ;LOWER PRIORITY RTS PC SCEND=. SCRSIZ=SCBUFR-SCBGIN+4 SCRTOT=/2 .SBTTL END .IIF DF NLOVLY, .LIST .END