;***************************************************************************;
;                                                                           ;
;                               UltraStat 3.x                               ;
;                           DEVICE STATUS SCREEN                            ;
;                                                                           ;
;***************************************************************************;
;Copyright (C) 1988 UltraSoft Corporation.  All Rights Reserved.
;
;Written by: David Pallmann
;
;All edit history for USTAT is in USYM.M68.

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

;--- Include files

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

;--- Device Scanning Loop

DEV.SCAN::
       MOV     DEVTBL,A0               ; point to base of job table
       LEA     DIB,DT.TBL(MEM)
       MOVB    JOB.ROW(MEM),ROW(MEM)   ; set starting job row
       CLRB    JOB.UPDATE(MEM)         ; clear new arrow row
       CLRW    DEV.COUNT(MEM)          ;

DEV.BYPASS:
       MOVWL   JOB.OFFSET(MEM),D0
       BEQ     DEV.LOOP
10$:    TST     DV.NXT(A0)
       JEQ     SNOOZE
       MOV     DV.NXT(A0),A0
       ADD     #DT.SIZ,DIB
       INCW    DEV.COUNT(MEM)          ;
       SOB     D0,10$

DEV.LOOP:
       KEY     GET.COMMAND
       BIT     #F$UPDATE,FLAGS(MEM)
       BEQ     10$
       OR      #DT$NEW,DT.FLG(DIB)
10$:    MOV     A0,DCB

;--- Handle a device

UPDATE.DEVICE:
       CALL    DEV.NAME
       KEY     10$
       CALL    DEV.SIZE
       KEY     10$
       CALL    DEV.INUSE
       KEY     10$
       CALL    DEV.NOTES
       AND     #^C<DT$NEW>,DT.FLG(DIB)
10$:    CALL    ARROW

DEV.NEXT::
       INCW    DEV.COUNT(MEM)          ;
       TST     DV.NXT(A0)
       JEQ     SNOOZE
       ADD     #DT.SIZ,DIB
       MOV     DV.NXT(A0),A0
       INCB    ROW(MEM)                ; increment display row
       CMMB    ROW(MEM),LAST.ROW(MEM)  ; end of page?
       JLOS    DEV.LOOP                ;  no - on to next device
       JMP     SNOOZE

;--- Update device name (three letter code and unit)

DEV.NAME:
       MOVW    DV.DEV(DCB),D0
       MOVW    DV.UNT(DCB),D2
       BIT     #DT$NEW,DT.FLG(DIB)
       BNE     10$
       CMPW    D0,DT.DEV(DIB)
       BNE     10$
       CMPW    D2,DT.DRV(DIB)
       REQ
10$:    MOVW    D0,DT.DEV(DIB)
       MOVW    D2,DT.DRV(DIB)
       MOVW    DV.FLG(DCB),DT.NOT(DIB)
       CURSOR  ROW(MEM),#2
       HIGH
       OUTDEV  DT.DEV(DIB)
       MOVWL   D2,D1
       DCVT    0,OT$TRM
       TYPESP  :
       MOVB    ROW(MEM),JOB.UPDATE(MEM)
       CALL    LOCATE.DRIVER
       RTN

LOCATE.DRIVER:
       CLR     DT.DVR(DIB)
       CMPW    DT.DEV(DIB),#[DSK]
       BEQ     10$
       MOVW    DT.DEV(DIB),TEMP(MEM)
       CLRW    TEMP+2(MEM)
       MOVW    #[DVR],TEMP+4(MEM)
       SRCH    TEMP(MEM),A6
       BEQ     20$
       RTN
10$:    MOV     ZSYDSK,A6
20$:    MOV     A6,DT.DVR(DIB)
       RTN

;--- Update device size

DEV.SIZE:
       CLR     D0
       BITW    #DV$MNT,DT.NOT(DIB)
       BEQ     10$
       MOV     DT.DVR(DIB),D6
       BEQ     10$
       MOV     D6,A6
       MOV     DD.DSZ(A6),D0
10$:    BIT     #DT$NEW,DT.FLG(DIB)
       BNE     20$
       CMP     D0,DT.MAX(DIB)
       REQ
20$:    MOV     D0,DT.MAX(DIB)
       CURSOR  ROW(MEM),#9.
       HIGH
       MOV     D0,D1
       BEQ     30$
       DCVT    7,OT$TRM!OT$ZER
       BR      40$
30$:    TYPE    <       >
40$:    MOVB    ROW(MEM),JOB.UPDATE(MEM)
       RTN

;--- Update device blocks in use (and, blocks free)

DEV.INUSE:
       CLR     D0
       TST     DT.DVR(DIB)             ; do we know address of driver?
       BEQ     100$                    ;  no - forget about bitmap
       BITW    #DV$MNT,DT.NOT(DIB)     ; is this device mounted?
       BEQ     100$                    ;  no - forget about bitmap
       MOV     DT.MAX(DIB),D2          ; get #blocks into D2
       CALL    READ.BITMAP             ; point A1 to bitmap
       BNE     100$                    ;  failed
;[116]  CLR     D5                      ; clear #blocks
;[116]10$:      MOV     #8.-1,D3
;[116]  MOVB    (A1)+,D1
;[116]  MOV     #1,D4
;[116]20$:      MOVB    D1,D7
;[116]  ANDB    D4,D7
;[116]  BEQ     30$
;[116]  INC     D5                      ; add 1 to count
;[116]30$:      ASL     D4                      ; update bit to test
;[116]  DEC     D2
;[116]  BEQ     40$
;[116]  DBF     D3,20$                  ; loop
;[116]  BR      10$
;[116]40$:      MOV     D5,D0
       MOV     INFO+DI.USE(MEM),D0     ; get blocks in use             [116]
       MOV     D0,D5                   ;                               [116]

;D0 now contains zero (non-disk or non-mounted device), or number of blocks
;in use

100$:   BIT     #DT$NEW,DT.FLG(DIB)
       BNE     110$
       CMP     D0,DT.INU(DIB)
       REQ
110$:   MOV     D0,DT.INU(DIB)
       MOVB    ROW(MEM),JOB.UPDATE(MEM)
       CURSOR  ROW(MEM),#17.
       HIGH
       MOV     D0,D1
       BNE     120$
       TYPE    <              >
       BR      DEV.FREE
120$:   DCVT    7,OT$TRM!OT$ZER
       TST     DT.MAX(DIB)
       JEQ     DEV.FREE
       MOV     DT.INU(DIB),D0
       MUL     D0,#100.
       MOV     DT.MAX(DIB),D2
       DIV     D0,D2
       AND     #177777,D0
       TYPE    < (>
       MOV     D0,D1
       CMP     D1,#100.
       BNE     130$
       CLR     D1
       TYPE    1
130$:   DCVT    2,OT$TRM!OT$ZER
       TYPESP  %)

DEV.FREE:
       CLR     D0
       TST     DT.INU(DIB)
       BEQ     10$
       MOV     DT.MAX(DIB),D0
       SUB     DT.INU(DIB),D0
10$:    MOV     D0,DT.FRE(DIB)
       CURSOR  ROW(MEM),#31.
       HIGH
       MOV     D0,D1
       BNE     20$
       TYPE    <              >
       RTN
20$:    DCVT    7,OT$TRM!OT$ZER
       TST     DT.MAX(DIB)
       REQ
       MOV     DT.FRE(DIB),D0
       MUL     D0,#100.
       MOV     DT.MAX(DIB),D2
       DIV     D0,D2
       AND     #177777,D0
       TYPE    < (>
       MOV     D0,D1
       CMP     D1,#100.
       BNE     30$
       CLR     D1
       TYPE    1
30$:    DCVT    2,OT$TRM!OT$ZER
       TYPESP  %)
       RTN

;RETURN BITMAP ADDR IN A1 FOR DEVICE @DCB
;determine if bitmap is paged or not.  If it is paged, we must read the
;bitmap from disk to insure that we have the right one.  If bitmap is not
;paged, we can speed things up tremendously by directly accessing the bitmap
;already in memory.

READ.BITMAP:
       SAVE    A0,A2-A5,D0-D5
;[116]  MOV     DV.BMP(DCB),D7          ; address bitmap DDB+flags+buffer       [1.3]
;[116]  BEQ     20$                     ; no bitmap
;[116]  MOV     D7,A1
;[116]  BITW    #BM$PAG,D.DDB(A1)       ; is bitmap paged?              [1.3]
;[116]  BNE     10$                     ;  yes, it is                   [1.3]
;[116]  BITW    #BM$VLD,D.DDB(A1)       ; is bitmap valid for this device?
;[116]  BEQ     10$                     ;  no
;[116]  ADD     #D.DDB+2,A1             ;  no - point to in-memory bitmap
;[116]  TST     @A1                     ; is first lword zeroed?        [1.3]
;[116]  BEQ     10$                     ;  yes - load bitmap to be sure [1.3]
;[116]  REST    A0,A2-A5,D0-D5
;[116]  LCC     #PS.Z
;[116]  RTN                             ; return                        [1.3]
;[116] 10$:
       MOVW    DV.DEV(DCB),DISK+D.DEV(MEM)
       MOVW    DV.UNT(DCB),DISK+D.DRV(MEM)
       CLR     DISK+D.FIL(MEM)
       CLRW    DISK+D.EXT(MEM)
       CLRW    DISK+D.PPN(MEM)
       MOV     DT.DVR(DIB),DISK+D.DVR(MEM) ; DEBUG                     [116]

       LEA     A0,INFO(MEM)            ;                               [116]
       CLEAR   @A0,DI.SIZ              ; clear disk info area          [118]
       LEA     A2,DISK(MEM)            ;                               [116]
       CALL    DSKINF                  ;                               [116]

;[116]  DSKBMR  DISK(MEM)               ; read bitmap from disk         [1.3]
;[116]  MOV     DISK+D.ARG(MEM),A1      ; point A1 to bitmap area       [1.3]
;[116]  ANDW    #^C<BM$LOK>,-2(A1)      ; clear bitmap lock             [1.3]
       REST    A0,A2-A5,D0-D5
       LCC     #PS.Z
       RTN                             ; return                        [1.3]
20$:    REST    A0,A2-A5,D0-D5
       LCC     #0
       RTN

;--- Update device notes

DEFINE  OUT1    FLAG,TEXT
       BITW    #FLAG,DT.NOT(DIB)
       BEQ     1$$
       TYPESP  TEXT
1$$:
       ENDM

DEV.NOTES:
       MOVWL   DV.FLG(DCB),D0
       AND     #DV$MNT!DV$LOG!DV$14D!DV$NAC!DV$ASN!DV$SHR,D0
       BIT     #DT$NEW,DT.FLG(DIB)
       BNE     10$
       CMPW    D0,DT.NOT(DIB)
       REQ
10$:    MOVW    D0,DT.NOT(DIB)
       HIGH
       CURSOR  ROW(MEM),#46.
       CLREOL
       OUT1    DV$SHR,sharable
       OUT1    DV$ASN,assigned to
       BITW    #DV$ASN,DT.NOT(DIB)
       BEQ     20$
       MOV     DV.JCB(DCB),A6
       OUTNAM  JOBNAM(A6)
20$:    OUT1    DV$MNT,mounted
;;      OUT1    DV$LOG,logical
       OUT1    DV$14D,extended
       OUT1    DV$NAC,private
       MOVB    ROW(MEM),JOB.UPDATE(MEM)
       CALL    DISK.LABEL
       RTN

;--- output disk label if (a) in wide mode, (b) device mounted, and (c)
;    driver located.

DISK.LABEL:
       BIT     #F$WIDE,FLAGS(MEM)
       REQ
       BITW    #DV$MNT,DT.NOT(DIB)
       REQ
       TST     DT.DVR(DIB)
       REQ
       MOVW    DT.DEV(DIB),DISK+D.DEV(MEM)
       MOVW    DT.DRV(DIB),DISK+D.DRV(MEM)
       MOV     DT.DVR(DIB),DISK+D.DVR(MEM)
       CLR     DISK+D.REC(MEM)
       READ    DISK(MEM)
       MOV     DISK+D.BUF(MEM),A2
       CURSOR  ROW(MEM),#78.
       HIGH
       CMPW    LB.HDR(A2),#125252      ; labelled?
       BNE     10$                     ;  no
       CMPW    LB.HDR+2(A2),#52525     ; labelled?
       BNE     10$                     ;  no
       TTYL    LB.VLN(A2)              ; output volume name
       TSTB    LB.VID(A2)              ; is there an Id?
       BEQ     10$                     ;  no - skip the parentheses
       TYPE    < (>
       TTYL    LB.VID(A2)              ; volume Id
       TYPE    )
10$:    CLREOL
       RTN

       END