;****************************************************************************
;*                                                                          *
;*                              UltraStat 3.x                               *
;*                       HEADER DISPLAY AND REFRESH                         *
;*                                                                          *
;****************************************************************************
;Copyright (C) 1988, 1989 UltraSoft Corporation.  All Rights Reserved.
;
;Written by: David Pallmann
;
;All edit history for USTAT is in USYM.M68.

       ASMMSG  "== UltraStat 3.x (HEADER) =="
       AUTOEXTERN

;--- Include files

       SEARCH  SYS
       SEARCH  SYSSYM
       SEARCH  TRM
       COPY    DSKINF.CPY
       COPY    USYM/L

;-- Clear screen and display background text

HEADER::
       CLS                             ; clear the screen
       MOVB    #3,JOB.ROW(MEM)         ; set starting job row
       CLRB    JOB.ARROW(MEM)          ; no previous job arrow
       LEA     A0,HD.TBL(MEM)
       CLR     HD.DAT(A0)              ; force update of date
       CLR     HD.TIM(A0)              ; force update of time
       CLR     HD.UPT(A0)              ; force update of uptime
       CLRW    HD.JOB(A0)              ; job count
       CLRW    HD.ACT(A0)              ; active job count
       CLRW    HD.CPB(A0)              ; CPU-bound jobs
       CLRW    HD.IOB(A0)              ; I/O-bound jobs

;--- Output reverse video bar on top line of screen, containing system
;    name, operating system name, operating system version, and CPU type.
;    Output properly for mode terminals as well as field terminals.

TOPLIN: FWHITE                          ; white fgd                     [110]
       HIGH                            ; high intensity
       CURSOR  #1,#80.                 ; (1,80)
       CALL    END.REVERSE
       CURSOR  #1,#1                   ; (1,1)
       CALL    START.REVERSE
       TTYL    SPACES                  ; output 78 spaces for mode terminals
       CURSOR  #1,#2                   ; (1,2)
       TYPE    < Status of >           ;
       TTYL    SYSNAM                  ; output operating system name
       TYPE    < version >
       MOV     #2,A0                   ; output
       VCVT    @A0,OT$TRM              ;  operating system version

FLAG.OPR:                               ;                               [105]
       BIT     #F$OPR,FLAGS(MEM)       ; in operator mode?             [105]
       BEQ     10$                     ;  no                           [105]
       CURSOR  #1,#46.                 ;                               [105]
       FRED                            ; red fgd                       [110]
       TYPE    <SYSTEM OPERATOR MODE > ;                               [105]
10$:                                    ;                               [105]

FLAG.LOG:
       BIT     #F$OPR,FLAGS(MEM)       ; in operator mode?             [105]
       BNE     10$                     ;  yes - no room to show mode   [105]
       BIT     #F$LOG,FLAGS(MEM)
       BEQ     10$
       CURSOR  #1,#46.
       FRED                            ; red fgd                       [110]
       TYPE    <LOG-ALERT>
10$:

FLAG.PROG:
       BIT     #F$OPR,FLAGS(MEM)       ; in operator mode?             [105]
       BNE     10$                     ;  yes - no room to show mode   [105]
       BIT     #F$PROG,FLAGS(MEM)
       BEQ     10$
       CURSOR  #1,#57.
       FRED                            ; red fgd                       [110]
       TYPE    <PROG-ALERT>
10$:

SHOW.CPU:
       CURSOR  #1,#69.                 ; (1,69)
       FWHITE                          ; white fgd
       TYPE    CPU: 680
       BIT     #SY$M30,SYSTEM
       BNE     M68030
       BIT     #SY$M20,SYSTEM
       BNE     M68020
       BIT     #SY$M10,SYSTEM
       BNE     M68010
M68000: TYPE    00
       BR      ENDTOP
M68010: TYPE    10
       BR      ENDTOP
M68020: TYPE    20
       BR      ENDTOP
M68030: TYPE    30

ENDTOP: TYPESP
       CALL    END.REVERSE
       JMP     STATISTICS

START.REVERSE:
       BIT     #F$AM70,FLAGS(MEM)
       BEQ     10$
       RWHITE
       RTN
10$:    REVON
       RTN

END.REVERSE:
       BIT     #F$AM70,FLAGS(MEM)
       BEQ     10$
       WHITE
       RTN
10$:    REVOFF
       RTN

;--- Remainder of header, statistical information, may be selectively
;    enabled or disabled by the user.  Only output it if we are flagged to
;    do so.

DEFINE  OPTAT   R,C,TEXT
       CURSOR  #^D<R>,#^D<C>
       BLUE
       TYPE    TEXT
       RED
       ENDM

STATISTICS:
       BIT     #F$HEADER,FLAGS(MEM)    ; output header?
       JEQ     TITLE                   ;  no
       MOVB    #7,JOB.ROW(MEM)         ; adjust starting job row
       BIT     #F$AM70,FLAGS(MEM)
       JEQ     10$
       OPTAT   3,1,Date:
       OPTAT   3,20,Time:
       OPTAT   3,40,Day:
       OPTAT   3,60,Uptime:
       OPTAT   4,1,Total Jobs:
       OPTAT   4,20,Active Jobs:
       OPTAT   4,40,CPU Bound:
       OPTAT   4,60,IO Bound:
       OPTAT   5,1,Main Queue:
       OPTAT   5,20,Disk Queue:
       OPTAT   5,40,Print Queue:
       OPTAT   5,60,Cache:
       JMP     20$
10$:    LOW
       FWHITE                          ; white fgd                     [110]
       TYPEAT  3,2,Date:
       TYPEAT  3,21,Time:
       TYPEAT  3,41,Day:
       TYPEAT  3,61,Uptime:
       TYPEAT  4,2,Total Jobs:
       TYPEAT  4,21,Active Jobs:
       TYPEAT  4,41,CPU Bound:
       TYPEAT  4,61,IO Bound:
       TYPEAT  5,2,Main Queue:
       TYPEAT  5,21,Disk Queue:
       TYPEAT  5,41,Print Queue:
       TYPEAT  5,61,Cache:
20$:

TITLE:: CURSOR  JOB.ROW(MEM),#1
       CLREOS
       CALL    LINE24
       CURSOR  JOB.ROW(MEM),#1
       BIT     #F$AM70,FLAGS(MEM)
       BEQ     10$
       HIGH
       YELLOW
       BR      20$
10$:    FCYAN
       LOW
20$:    CMPW    MODE(MEM),#M$JOB
       JEQ     JOB.HEADER
       CMPW    MODE(MEM),#M$TERM
       JEQ     TERM.HEADER
       CMPW    MODE(MEM),#M$DEV
       JEQ     DEV.HEADER
       CLS
       TYPECR  ?Invalid mode
       JMP     FINISH

;--- Job Mode Header

JOB.HEADER:
       CURSOR  JOB.ROW(MEM),#80.
       UNDOFF
       CURSOR  JOB.ROW(MEM),#1
       UNDON
       CURSOR  JOB.ROW(MEM),#2
       FWHITE
       TYPE    <Job    Term   Account         Prog   State Mem CPU time   >
       BIT     #F$USER,FLAGS(MEM)
       BEQ     10$
       TYPE    <User name       >
       BR      20$
10$:    TYPE    <Reads Writes Pri>
20$:    BIT     #F$WIDE,FLAGS(MEM)
       BEQ     30$
       TYPE    <  Owner Level  Mem base  JCB base  TCB base>
30$:    UNDOFF
       BIT     #F$AM70,FLAGS(MEM)
       BEQ     32$
       CYAN
32$:    INCB    JOB.ROW(MEM)
       OR      #F$UPDATE,FLAGS(MEM)
       CALL    OPR.MARK                ;                               [105]
       JMP     HEADER.SCAN

;--- Terminal Mode Header

TERM.HEADER:
       CURSOR  JOB.ROW(MEM),#80.
       UNDOFF
       CURSOR  JOB.ROW(MEM),#1
       UNDON
       CURSOR  JOB.ROW(MEM),#2
       FWHITE
       TYPE    <Term   Job    IDV    TDV    Port Speed Buffer                            >
       UNDOFF
       FCYAN
       BIT     #F$AM70,FLAGS(MEM)
       BEQ     10$
       CYAN
10$:    INCB    JOB.ROW(MEM)
       OR      #F$UPDATE,FLAGS(MEM)
       JMP     HEADER.SCAN

;--- Device Mode Header

DEV.HEADER:
       CURSOR  JOB.ROW(MEM),#80.
       UNDOFF
       CURSOR  JOB.ROW(MEM),#1
       UNDON
       CURSOR  JOB.ROW(MEM),#2
       FWHITE
       TYPE    <Device    Size  In Use          Free        Comments                      >
       BIT     #F$WIDE,FLAGS(MEM)
       BEQ     10$
       TYPE    <  Disk Label                    >
10$:    FCYAN
       UNDOFF
       BIT     #F$AM70,FLAGS(MEM)
       BEQ     20$
       CYAN
20$:    INCB    JOB.ROW(MEM)
       OR      #F$UPDATE,FLAGS(MEM)
;fall   JMP     HEADER.SCAN

;--- Header Scanning Loop

HEADER.SCAN::
       BIT     #F$HEADER,FLAGS(MEM)
       BEQ     10$
       HIGH
       FGREEN
       LEA     A0,HD.TBL(MEM)
       KEY     GET.COMMAND
       CALL    HEADER.DATE
       KEY     GET.COMMAND
       CALL    HEADER.TIME
       KEY     GET.COMMAND
       CALL    HEADER.UPTIME
       KEY     GET.COMMAND
       CALL    HEADER.JOBS
       KEY     GET.COMMAND
       CALL    HEADER.QUEUE
       KEY     GET.COMMAND
       CALL    HEADER.DISK.QUEUE
       KEY     GET.COMMAND
       CALL    HEADER.PRINTER.QUEUE
       KEY     GET.COMMAND
       CALL    HEADER.CACHE
10$:    FCYAN
       CMPW    MODE(MEM),#M$JOB
       JEQ     JOB.SCAN
       CMPW    MODE(MEM),#M$TERM
       JEQ     TERM.SCAN
       CMPW    MODE(MEM),#M$DEV
       JEQ     DEV.SCAN
       CLS
       TYPECR  ?Invalid mode
       JMP     FINISH

;--- Update date in header

HEADER.DATE:
       GDATES  TEMP(MEM)               ; get the date in separated format
       CMM     TEMP(MEM),HD.DAT(A0)    ; did date change?
       REQ                             ;  no
       MOV     TEMP(MEM),HD.DAT(A0)    ; update storage
       HIGH
       CURSOR  #3,#8.
       MOVBL   HD.DAT+1(A0),D1
       DCVT    2,OT$TRM
       TYPE    -
       MOVB    HD.DAT(A0),D1
       LEA     A1,MONTH.TABLE
       DEC     D1
       MUL     D1,#4
       ADD     D1,A1
       TTYL    @A1
       TYPE    -
       MOVB    HD.DAT+2(A0),D1
       DCVT    2,OT$TRM

;--- update day of week also

       CURSOR  #3,#46.
       MOVBL   HD.DAT+3(A0),D1
       LEA     A1,DAY.TABLE
       MUL     D1,#10.
       ADD     D1,A1
       TTYL    @A1
       RTN

;--- Update time in header

HEADER.TIME:
       GTIMES  TEMP(MEM)               ; get the time in separated format
       CMM     TEMP(MEM),HD.TIM(A0)    ; did time change?
       REQ                             ;  no
       MOVB    #'A,D2                  ; assume AM
       MOV     TEMP(MEM),HD.TIM(A0)    ; update storage
       HIGH
       CURSOR  #3,#27.
       MOVBL   HD.TIM(A0),D1
       TST     D1                      ; 12:xx AM?
       BEQ     20$                     ;  yes
       CMP     D1,#12.                 ; 12:xx PM?
       BEQ     10$                     ;  yes
       BLO     30$                     ;  earlier
       SUB     #12.,D1                 ; subtract 12 from hours
10$:    MOV     #'P,D2                  ; set PM
       BR      30$
20$:    MOV     #12.,D1
30$:    DCVT    2,OT$TRM
       TYPE    :
       MOVB    HD.TIM+1(A0),D1
       DCVT    2,OT$TRM
       TYPE    :
       MOVB    HD.TIM+2(A0),D1
       DCVT    2,OT$TRM!OT$TSP
       MOVB    D2,D1
       TTY                             ; output A or P
       TYPE    M                       ; output M
       RTN

;--- Update uptime in header

HEADER.UPTIME:
       MOV     UPTIME,D0
       BIT     #F$UPDATE,FLAGS(MEM)
       BNE     10$
       CMM     D0,HD.UPT(A0)
       REQ
10$:    CURSOR  #3,#69.
       SUB     A2,A2
       MOV     D0,D1
       CALL    $OTCON
       RTN

;--- Update job counts

HEADER.JOBS:
       CLR     D0                      ; total job count
       CLR     D2                      ; active job count
       CLR     D3                      ; CPU-bound job count
       CLR     D4                      ; I/O-bound job count
       CLRW    HD.TBL+HD.ALC(MEM)      ; allocated job count           [105]
       MOV     JOBTBL,A1               ; point to job table
10$:    MOV     (A1)+,D6                ; get JCB address
       MOV     D6,A6                   ; (flags unchanged)
       BMI     HEADER.JOBS.UPDATE      ; end of job table
       BEQ     50$                     ; deallocated job
       INCW    HD.TBL+HD.ALC(MEM)      ; increment allocated job count [105]
       MOV     A6,A2                   ; A2 is JCB address
       MOVW    JOBSTS(A2),D1           ; CPU-bound job?
       BEQ     30$                     ;  yes
       BITW    #J.IOW,D1               ; I/O-bound?
       BNE     40$                     ;  yes
       BITW    #J.TOW,D1               ; I/O-bound?
       BNE     40$                     ;  yes
       BR      50$
30$:    INC     D3                      ; update CPU-bound job count
       INC     D2                      ; update active job count
       BR      50$
40$:    INC     D4                      ; update I/O-bound job count
       INC     D2                      ; update active job count
50$:    INC     D0                      ; update total job count
       BR      10$

;--- update header job statistics

HEADER.JOBS.UPDATE:
       BIT     #F$UPDATE,FLAGS(MEM)
       BNE     4$
       CMPW    D0,HD.JOB(A0)
       BEQ     10$
4$:     MOVW    D0,HD.JOB(A0)
       CURSOR  #4,#14.
       MOV     D0,D1
       DCVT    0,OT$TRM!OT$TSP
10$:    BIT     #F$UPDATE,FLAGS(MEM)
       BNE     14$
       CMPW    D2,HD.ACT(A0)
       BEQ     20$
14$:    MOVW    D2,HD.ACT(A0)
       CURSOR  #4,#34.
       MOV     D2,D1
       DCVT    0,OT$TRM!OT$TSP
20$:    BIT     #F$UPDATE,FLAGS(MEM)
       BNE     24$
       CMPW    D3,HD.CPB(A0)
       BEQ     30$
24$:    MOVW    D3,HD.CPB(A0)
       CURSOR  #4,#52.
       MOV     D3,D1
       DCVT    0,OT$TRM!OT$TSP
30$:    BIT     #F$UPDATE,FLAGS(MEM)
       BNE     34$
       CMPW    D4,HD.IOB(A0)
       BEQ     40$
34$:    MOVW    D4,HD.IOB(A0)
       CURSOR  #4,#71.
       MOV     D4,D1
       DCVT    0,OT$TRM!OT$TSP
40$:    RTN

;--- update free queue blocks

HEADER.QUEUE:
       MOV     QFREE,D0
       BIT     #F$UPDATE,FLAGS(MEM)
       BNE     10$
       CMP     D0,HD.QUE(A0)
       REQ
10$:    MOV     D0,HD.QUE(A0)
       CURSOR  #5,#14.
       MOV     D0,D1
       DCVT    0,OT$TRM!OT$TSP
       RTN

;--- update disk queue

HEADER.DISK.QUEUE:
       CLR     D0
       MOV     #DDBCHN,A6
10$:    TST     @A6
       BEQ     20$
       INC     D0
       MOV     @A6,A6
       BR      10$
20$:    BIT     #F$UPDATE,FLAGS(MEM)
       BNE     30$
       CMP     D0,HD.DKQ(A0)
       REQ
30$:    MOV     D0,HD.DKQ(A0)
       CURSOR  #5,#33.
       MOV     D0,D1
       DCVT    0,OT$TRM!OT$TSP
       RTN

;--- update printer queue

HEADER.PRINTER.QUEUE:
       CLR     D0
       MOV     LPTQUE,D6
       BEQ     40$
10$:    MOV     D6,A1
       MOV     PR.QUE(A1),D7
       BEQ     30$
20$:    INC     D0
       MOV     D7,A6
       MOV     PQ.LNK(A6),D7
       BNE     20$
30$:    MOV     PR.LNK(A1),D6
       BNE     10$
40$:    BIT     #F$UPDATE,FLAGS(MEM)
       BNE     50$
       CMP     D0,HD.PRQ(A0)
       BEQ     60$
50$:    MOV     D0,HD.PRQ(A0)
       CURSOR  #5,#54.
       MOV     D0,D1
       DCVT    0,OT$TRM!OT$TSP
60$:    RTN

;--- update cache hit rate

HEADER.CACHE:
       SAVE    A0-A5,D0-D5
       CLR     TEMP(MEM)
       CLRW    TEMP+4(MEM)
       CLR     TEMP+6(MEM)             ; pre-clear output buffer       [113]
       TST     HD.CAD(A0)
       BEQ     90$
       MOV     HD.TBL+HD.CAD(MEM),A0
       MOV     CACHE.TOTAL(A0),D2      ; get total reads
       MOV     CACHE.READS(A0),D3      ; get cache reads
       MOV     D2,D4                   ; calculate disk reads by
       SUB     D3,D4                   ;   subtracting cache reads from total reads
       LEA     A2,TEMP+6(MEM)          ; index total reads in FP
       LEA     A3,TEMP(MEM)            ; index cache reads in FP
       FLTOF   D2,@A2                  ; convert total reads to FP
       FLTOF   D3,@A3                  ; convert cache reads to FP
       FDIV    A2,A3                   ; divide total reads into cache reads
       FPWR    @A3,#2                  ; multiply result by 100 to get %
       LEA     A2,TEMP+6(MEM)
       FCVT    @A3,4,OT$FIX!OT$MEM,1,0 ; display hit rate
       CLRB    @A2
90$:    BIT     #F$UPDATE,FLAGS(MEM)
       BNE     92$
       CMM     TEMP+6(MEM),HD.TBL+HD.CAC(MEM)
       BEQ     99$
92$:    MOV     TEMP+6(MEM),HD.TBL+HD.CAC(MEM)
       CURSOR  #5,#67.
       TSTB    TEMP+6(MEM)
       BEQ     93$
       TTYL    TEMP+6(MEM)
       TYPE    <%>
93$:    TYPE    <   >
99$:    REST    A0-A5,D0-D5
       RTN

MONTH.TABLE:
       ASCIZ   /Jan/                   ; January
       ASCIZ   /Feb/                   ; February
       ASCIZ   /Mar/                   ; March
       ASCIZ   /Apr/                   ; April
       ASCIZ   /May/                   ; May
       ASCIZ   /Jun/                   ; June
       ASCIZ   /Jul/                   ; July
       ASCIZ   /Aug/                   ; August
       ASCIZ   /Sep/                   ; September
       ASCIZ   /Oct/                   ; October
       ASCIZ   /Nov/                   ; November
       ASCIZ   /Dec/                   ; December

DAY.TABLE:
       ASCIZ   /Monday   /             ; Monday
       ASCIZ   /Tuesday  /             ; Tuesday
       ASCIZ   /Wednesday/             ; Wednesday
       ASCIZ   /Thursday /             ; Thursday
       ASCIZ   /Friday   /             ; Friday
       ASCIZ   /Saturday /             ; Saturday
       ASCIZ   /Sunday   /             ; Sunday
       EVEN                            ;                               [105]

       END