.TITLE UTX .SBTTL INTRO PAGE ; ; UTL IS A TASK TO DISPLAY THE STRUCTURE OF THE USER TASK LIST ; ; UTL WILL DISPLAY THE RELATIVE RANKING OF TASKS ON EACH OF THE ; N LEVELS AND WILL DISPLAY FLAGS FOR: ; NEXT TASK TO SWAP ; NEXT TASK TO LOAD ; ROBIN POINTER ; ; AFTER RUNNING VIA A: ; ; MCR>UTL (TO RUN EVERY 60 CLOCK TICKS) ; OR: ; ; MCR>UTL 15 (TO RUN EVERY 15 CLOCK TICKS) ; ; ; UTL WILL DISPLAY THE UTL AND UPDATE ITSELF EVERY N TICKS ; ; A CONTROL C WHILE THE TASK IS RUNNING WILL CAUSE IT TO EXIT AFTER THE ; END OF THE NEXT DISPLAY ; ; APRIL 1979 -- FRANK BORGER (MICHAEL REESE MEDICAL CENTER) ; ; CORRECTED FOR BUFFER OVERFLOW 19-APR-79 LARRY SIMPSON ; ; ; ; .MCALL DIR$,QIOW$,MRKT$,EXIT$S,GMCR$,WTSE$,ASTX$ .MCALL TTSYM$ TTSYM$ .SBTTL DIRECTIVE PARAMTER BLOCKS ; ;GET MCR ; GMCR: GMCR$ ; ;QIO TO WRITE LINE ; QIO: QIOW$ IO.WVB,5,1,,IOST,, ; ;QIO FOR DIRECT CURSOR ADDRESS ; CURQIO: QIOW$ IO.WLB!IO.WAL,5,1,,,, ; ;QIO FOR BEEHIVE CURSOR MOVE ; BEEQIO: QIOW$ IO.WLB!IO.WAL,5,1,,,, ; ; GET TERMINAL DPB AND IOSB ; GETTYP: QIOW$ SF.GSC,5,1,,IOTY,, IOTY: .WORD 0 ;DPB TYPE: .WORD 0 ;TERM TYPE GOES HERE ; ;ATTACH WITH ^C AST QIO ; ATT: QIOW$ IO.ATA,5,1,,IOST,, ; ;DETACH ; DET: QIOW$ IO.DET,5,1,,IOST,,<> ; ;SET VT100 TO VT52 MODE ; SVT52: QIOW$ IO.WLB!IO.WAL,5,1,,,, ; ;SET VT100 BACK TO VT100 MODE ON EXIT ; SV100: QIOW$ IO.WLB!IO.WAL,5,1,,,, ; ;EXIT AST'S ; ASTEXI: ASTX$ ; ;60 TICK MARK TIME (CAN BE CHANGED) ; MARK: MRKT$ 2,60.,1 ; ;WAIT FOR MARK TIME ; WAIT: WTSE$ 2 ; .SBTTL STORAGE AREA ESCCHR: .ASCIZ /=/ ;ESCAPE CHARACTER FOR SOROC EXITFL: .WORD 0 ;FLAG FOR EXIT PENDING NLEVEL: .WORD 0 ;NUMBER OF LEVELS SPSAVE: .WORD 0 ;SAVE STACK POINTER HERE IOST: .WORD 0,0 ;IO STATUS BLOCK ; LINE: .BYTE 33 HOME: .ASCII /*/ .BYTE 33 CLEAR: .ASCII /E/ ;INITIALLY HOME & CLEAR FOR SOROC .BLKW 3 ;6 NULLS SO IT WORKS .ASCII / LEVEL 1 LEVEL 2 LEVEL 3 LEVEL 4/ .ASCII / LEVEL 5 LEVEL 6/ LINELN=.-LINE .EVEN ; ;ASSURE TERMINAL IN VT52 MODE ; V52: .BYTE 33 ;'ESC' .BYTE 133 ;'[' .BYTE 77 ;'?' .BYTE 62 ;'2' .BYTE 154 ;'l' V52L=.-V52 ; ;RETURN TERMINAL TO VT100 MODE ; V100: .BYTE 33 ;'ESC' .BYTE 74 ;'<' .BYTE 33 ;'ESC' SEQUENCE FOR TELEVIDEO .BYTE 133 ;'[' IGNORED ON VT100'S AND SW10'S .BYTE 66 ;'6' .BYTE 63 ;'3' .BYTE 73 ;';' .BYTE 61 ;'1' .BYTE 42 ;'"' .BYTE 160 ;'P' V100L=.-V100 ; ;BEEHIVE CURSOR ADDRESSING LINE ; BEEBUF: .BYTE 33 .ASCII /H/ .BYTE 12 .REPT 6 .ASCII / / .ENDR .EVEN ; CURBUF: .BLKB 200 ;LARGE BUFFER FOR CURSOR ADDRESSING CUREND: .BLKB 34 ;OVERFLOW AREA ; ; ;SAVE AREA FOR LAST DISPLAY, SAVE NUMBER OF TASKS/LEVEL ;CURRENTLY MAXIMUM OF 6 LEVELS ; DISNUM: .BLKW 6 ; ;ROOM FOR 6 LEVELS OF UTL DATA ;FOR EACH LEVEL WILL STORE ; ;0() NUMBER OF TASKS AT THIS LEVEL ;2() ROBIN POINTER ;4() NEXT JOB TO LOAD POINTER ;6() NEXT JOB TO SWAP POINTER ; BUFF: .BLKW 24. ; ; ;THE TASK WILL PUSH ON HIS STACK THE TASK NAMES OF THE VARIOUS TASKS ;IN EACH UTL LEVEL AND THE RECOVER THEM ; .SBTTL INTRO CODE START: DIR$ #GETTYP ;++002 GET TERMINAL TYPE CMP TYPE,#T.V100 ;IS IT A VT100 BEQ 24$ ;IF SO, USE VT52 STUFF CMP TYPE,#T.VT52 ;VT 52 ?? BNE 1$ ;NO 24$: MOVB #'Y,ESCCHR ;YES, CHANGE ESC SEQUENCE MOVB #'H,HOME ;HOME SEQUENCE MOVB #'J,CLEAR ;AND CLEAR SEQUENCE 1$: CMP TYPE,#T.BEEH ;IS IT A BEEHIVE ? BNE 2$ ;NO MOV #-1,ESCCHR ;YES, FLAG IT AS NON-CURSOR ADDRESSING MOVB #'H,HOME ;CHANGE HOME SEQUENCE MOVB #'J,CLEAR ;AND CLEAR SEQUENCE 2$: DIR$ #GMCR ;GET MCR TO SET RECALL MOV #GMCR+6,R0 ;BUMP PAST "UTX " JSR PC,$CDTB ;GET # OF TICKS /SCAN CMP R1,#10 ;DO CHECK OF RANGE BLT 21$ ;TOO LOW, THEN BRANCH CMP R1,#300. ;EVERY 5 SECONDS IS MAX BGT 21$ MOV R1,MARK+M.KTMG ;CHANGE MARK TIME MAGNITUDE 21$: DIR$ #ATT ;ATTACH WITH AST'S CMP TYPE,#T.V100 ;IS IT A VT100? BNE 23$ ;NOPE DIR$ #SVT52 ;SET VT100 TO VT52 MODE SO CURSOR STUFF WORKS 23$: MOV #.UTLHD,R0 ;GET UTL LISTHEAD CLR R1 ;CLEAR COUNTER 22$: MOV (R0),R0 ;GET NEXT/FIRST LEVEL INC R1 ;COUNT A LEVEL CMP (R0),#.UTLHD ;BACK AT UTL LISTHEAD BNE 22$ ;NO MUL #13.,R1 ;MAKE R1 SIZE OF LINE ADD #10.,R1 MOV R1,QIO+Q.IOPL+2 ;FILL IN LENGTH DIR$ #QIO ;WRITE HEADER LINE .SBTTL STORE UTL DATA REGO: TST EXITFL ;EXIT PENDING BEQ 1$ ;NO CMP TYPE,#T.V100 ;IS IT A VT100? BNE 2$ ;NO. JUST DO THE DETATCH DIR$ #SV100 ;RETURN TERMINAL TO VT100 MODE. 2$: DIR$ #DET ;DETACH TERMINAL EXIT$S ;YES 1$: MOV SP,SPSAVE ;SAVE STACK POINTER SUB #30,SP ;MAKE ROOM FOR OUR SUB CALLS ETC MOV #BUFF,R5 ;POINT TO UTL DATA STORAGE AREA CLR NLEVEL ;CLEAR LEVEL COUNTER MOV #.UTLHD,R0 ;GET USER TASK LISTHEAD MOV (R0),R0 ;GET FIRST LEVEL STORE: MOV Z.NE(R0),(R5) ;SAVE NUMBER OF TASKS BIC #177400,(R5)+ ;CLEAR UPPER BYTE MOV Z.NT(R0),(R5)+ ;SAVE NEXT TASK TO RUN MOV Z.LD(R0),(R5)+ ;SAVE NEXT TASK TO LOAD MOV Z.NS(R0),(R5)+ ;SAVE NEXT TASK TO SWAP MOVB Z.NE(R0),R4 ;GET LOOP COUNTER BEQ 2$ ;DON'T STORE IF LEVEL EMPTY MOV Z.FJ(R0),R1 ;GET FIRST JOB NODE ADDRESS IN R1 1$: MOV X.TD(R1),R2 ;GET STD OF TASK IN R2 MOV S.TN(R2),-(SP) ;SAVE NAME MOV S.TN+2(R2),-(SP) MOV X.TI(R1),-(SP) ;SAVE TI POINTER CMP SP,#20 ;ARE WE TOO FULL ? BLT SHOW ;IF SO, DON'T SAVE ANY MORE MOV R1,-(SP) ;SAVE UTL NODE ADDRESS FOR AN ID MOV (R1),R1 ;GET NEXT JOB NODE ADDRESSS SOB R4,1$ ;DO UNTIL ALL JOBS AT THIS LEVEL FOUND 2$: INC NLEVEL ;COUNT A LEVEL MOV (R0)+,R0 ;GET NEXT LEVEL CMP R0,#.UTLHD ;BACK AT START ? BEQ SHOW ;IF SO DISPLAY BR STORE ;ELSE TRY FOR NEXT LEVEL .SBTTL SHOW TASKS SHOW: ; ;DURING THIS CODE, REGISTER USAGE IS AS FOLLOWS ; ;R0 = POINTER TO CURRENT OUTPUT BUFFER BEING ASSEMBLED ;R1 = POINTER TO LEVEL STORAGE AREA IN "BUFF:" ;R2 = ;R3 = USED TO READ SAVED DATA BACK OFF STACK ;R4 = CURRENT LEVEL (0 = FIRST LEVEL) ;R5 = CURRENT TASK AT THIS LEVEL (0 = FIRST TASK) ; MOV SPSAVE,SP ;RESET STACK TO START MOV SP,R3 ;SET R3 TO READ SAVED DATA SUB #30,R3 CLR R4 ;START AT LEVEL 0 MOV #CURBUF,R0 ;POINT R0 TO OUTPUT ASCII BUFFER MOV #BUFF,R1 ;POINT TO FIRST LEVEL IN "BUFF" DISLEV: MOV #1,R5 ;START AT FIRST TASK IN LEVEL TST ESCCHR ;IS IT A BEEHIVE BPL DISTAS ;NO CMP R0,#CURBUF ;ANYTHING LEFT TO OUTPUT FROM LAST LEVEL ? BEQ 111$ ;NO SUB #CURBUF,R0 ;GET SIZE MOV R0,CURQIO+Q.IOPL+2 ;AND RESET IN DPB DIR$ #CURQIO ;DO IT MOV #CURBUF,R0 ;RESET POINTER 111$: ;DO LF,SPACE POSITIONING FOR BEEHIVE MOV R1,-(SP) ;SAVE USED REG MOV R4,R1 ;GET LEVEL MUL #13.,R1 ;MULTIPLY BY 13 TO GET POSITION ADD #3,R1 ;ACCOUNT FOR INITIAL ESC,H,LF MOV R1,BEEQIO+Q.IOPL+2 ;FILL IN LENGTH MOV (SP)+,R1 ;RESTORE REG DIR$ #BEEQIO ;MOVE CURSOR TO TOP OF LEVEL LIST DISTAS: CMP R5,0(R1) ;DONE WITH TASKS AT THIS LEVEL ? BGT LEVDON ;IF SO, SEE IF NEED TO DELETE SOME JSR PC,DISONE ;ELSE DISPLAY THIS TASK INC R5 ;COUNT A TASK BR DISTAS ;AND DISPLAY ANOTHER LEVDON: DEC R5 ;MAKE ACTUAL NUMBER OF TASKS FOUND MOV R4,R2 ;GET LEVEL # ASL R2 ;MAKE IT WORD OFFSET ADD #DISNUM,R2 ;POINT TO NUMBER OF TASKS LAST TIME CMP R5,(R2) ;COMPARE BEQ NODIFF ;SAME NUMBER BGT ADDSOM ;MORE THIS TIME MOV R2,-(SP) ;SAVE R2 WIPED IN ERASE CALL JSR PC,ERASE ;SOME TO ERASE MOV (SP)+,R2 ;RESTORE HIM ADDSOM: MOV R5,(R2) ;MORE TASKS, UPDATE NUMBER DISPLAYED NODIFF: ;SAME NUMBER OF TASKS AT THIS LEVEL INC R4 ;GO TO NEXT LEVEL ADD #10,R1 ;UPDATE BUFF POINTER CMP SP,#20 ;ARE WE NEARING END OF STACK ? BLT FULL ;IF SO, QUIT DISPLAYING CMP R4,NLEVEL ;CHECK NUMBER OF LEVELS DISPLAYED BLT DISLEV ;IF NOT ALL, DISPLAY ANOTHER FULL: CMP R0,#CURBUF ;ANYTHING LEFT TO OUTPUT ? BEQ NONE ;NO SUB #CURBUF,R0 ;GET SIZE MOV R0,CURQIO+Q.IOPL+2 ;AND RESET IN DPB DIR$ #CURQIO ;DO IT NONE: MOV #CURBUF,R0 ;RESET POINTER DIR$ #MARK ;WAIT ONE SECOND DIR$ #WAIT ;WAIT FOR IT JMP REGO ;AND GO AGAIN ; ;ENTRY FOR CONTROL C SEEN ; CCENT: INC EXITFL ;SHOW EXIT PENDING DIR$ #ASTEXI ;EXIT AST .SBTTL DISPLAY TASK ;ENTER WITH ;R0 = POINTER TO CURRENT ASCII OUTPUT BUFFER ;R1 = POINTER TO LEVEL STORAGE AREA IN "BUFF" ;R2 = AVAILABLE (WIPED BY $C5TA) ;R3 = POINTER TO SAVED TASK DATA ON STACK ;R4 = CURRENT LEVEL (0 = FIRST LEVEL) ;R5 = CURRENT TASK AT THIS LEVEL (1 = FIRST TASK @ LEVEL) DISONE: MOV R1,-(SP) ;SAVE R1 FOR LATER USE TST ESCCHR ;IS THIS A BEEHIVE BPL 222$ ;NO MOVB #12,(R0)+ ;YES ,JUST DO LINE-FEED BR 333$ ;AND FORGET ABOUT DIRECT CURSOR ADDRESSING 222$: MOVB #33,(R0)+ ;FILL IN ESC SEQ MOVB ESCCHR,(R0)+ ;FOR SCOPE MOV R5,R1 ;GET TASK NUMBER ADD #41,R1 ;MAKE IT Y POSITION MOVB R1,(R0)+ MOV R4,R1 ;GET LEVEL # MUL #13.,R1 ;13 COLUMNS BETWEEN LEVELS ADD #40,R1 ;COLUMN 1 = 40 MOVB R1,(R0)+ 333$: MOV -(R3),R1 ;GET FIRST HALF OF TASK NAME JSR PC,$C5TA ;CONVERT TO ASCII MOV -(R3),R1 ;GET 2ND HALF OF TASK NAME JSR PC,$C5TA MOVB #40,(R0)+ ;PUT IN SPACE MOV -(R3),R1 ;GET PUD POINTER MOVB U.DN(R1),(R0)+ ;FILL IN TI NAME MOVB U.DN+1(R1),(R0)+ MOV R2,-(SP) MOV R3,-(SP) MOVB U.UN(R1),R3 ;GET UNIT NUMBER CLR R2 ;CLEAR UPPER REG DIV #10,R2 ;SEPERATE DIGITS OF DEV NUMBER BIS #60,R2 ;CONVERT UPPER DIGIT TO ASCII MOVB R2,(R0)+ BIS #60,R3 ;CONVERT REM (LOWER DIGIT) TO ASCII MOVB R3,(R0)+ MOV (SP)+,R3 ;RESTORE REG'S MOV (SP)+,R2 MOV -(R3),R2 ;GET UTL ADDRESS MOV (SP)+,R1 ;RECOVER LEVEL STORAGE AREA POINTER MOVB #40,(R0) ;PUT IN A SPACE FOR FLAG CMP R2,2(R1) ;IS IT ROBIN POINTER ? BNE 1$ MOVB #162,(R0) ;IF SO, SET FLAG 1$: CMP R2,4(R1) ;OR NEXT JOB TO SWAP ? BNE 2$ MOVB #163,(R0) ;IF SO, SET FLAG 2$: CMP R2,6(R1) ;OR NEXT JOB TO LOAD ? BNE 3$ MOVB #154,(R0) ;IF SO, SET FLAG 3$: INC R0 ;ADJUST FOR SPACE OR FLAG CHARACTER TST ESCCHR ;A BEEHIVE ? BPL 4$ ;NO MOV R3,-(SP) ;YES, DO 12. BACKSPACES MOV #12.,R3 ;SET COUNTER 555$: MOVB #10,(R0)+ ;PUT IN BACKSPACE SOB R3,555$ ;12. TIMES MOV (SP)+,R3 4$: JSR PC,OUTCHK ;CHECK FOR BUFFER OVERFLOW RTS PC .SBTTL ERASE OLD TASK ; ;SUB TO ERASE TASKS AT END OF A LEVEL WHEN THE NUMBER OF TASKS AT ;THAT LEVEL DECREASES ; ;CALL WITH ; ;R5 = FIRST TASK AT LEVEL TO BE ERASED ;(R2) = NUMBER OF TASKS LAST TIME WE DISPLAYED ;R4 = CURRENT LEVEL ; ERASE: MOV (R2),R2 ;NUMBER OF TASKS LAST TIME SUB R5,R2 ;MINUS NUMBER NOW = ERASE COUNT MOV R2,-(SP) ;SAVE COUNT FOR LATER ERALOO: MOV R1,-(SP) ;SAVE R1 TST ESCCHR ;IS THIS A BEEHIVE BPL 222$ ;NO MOVB #12,(R0)+ ;YES ,JUST DO LINE-FEED BR 333$ ;AND FORGET ABOUT DIRECT CURSOR ADDRESSING 222$: MOVB #33,(R0)+ ;PUT IN AN ESCAPE MOVB ESCCHR,(R0)+ ;FOR SCOPE MOV R5,R1 ;GET TASK NUMBER ADD #42,R1 ;MAKE IT Y POSITION (OFFSET BY 1 CAS R5 WAS ;LAST DISPLAYED TASK) MOVB R1,(R0)+ MOV R4,R1 ;GET LEVEL # MUL #13.,R1 ;13 COLUMNS BETWEEN LEVELS ADD #40,R1 ;COLUMN 1 = 40 MOVB R1,(R0)+ 333$: MOV #12.,R1 ;DO 12 SPACES 1$: MOVB #40,(R0)+ SOB R1,1$ MOV (SP)+,R1 ;RESTORE R1 INC R5 ;COUNT AN ERASE TST ESCCHR ;A BEEHIVE ? BPL 4$ ;NO MOV R3,-(SP) ;YES, DO 12. BACKSPACES MOV #12.,R3 ;SET COUNTER 555$: MOVB #10,(R0)+ ;PUT IN BACKSPACE SOB R3,555$ ;12. TIMES MOV (SP)+,R3 4$: JSR PC,OUTCHK ;CHECK FOR BUFFER OVERFLOW SOB R2,ERALOO ;AND DO R2 ERASES SUB (SP)+,R5 ;MAKE R5 RIGHT AGAIN RTS PC .SBTTL CHECK FOR BUFFER OVERFLOW ; ; OUTCHK - SUBROUTINE TO CHECK FOR BUFFER OVERFLOW AND ; PRINT OUTP BUFFER AND RESET BUFFER POINTER IF OVERFLOW ; ;ON ENTRY ; ; R0 HAS CURRENT OUTPUT BUFFER POINTER ; ; ON EXIT ; R0 UNCHANGED IF NO OVERFLOW ; ELSE IF OVERFLOW R0=CURBUF AND BUFFER PRINTED ; ; OTHER REGISTERS USED - NONE ; OUTCHK: CMP R0,#CUREND ;ARE WE OVERFLOWING OUTPUT BUFFER ? BLT 1$ ;NO SUB #CURBUF,R0 ;YES, GET SIZE MOV R0,CURQIO+Q.IOPL+2 ;SET LENGTH OF QIO DIR$ #CURQIO ;OUTPUT THE BUFFER MOV #CURBUF,R0 ;RESET OUTPUT BUFFER START 1$: RTS PC .END START