	.TITLE	VOL - MCR VOLUME DISPLAY TASK
	.IDENT	/V02.0/
	.NLIST	ME,BEX,CND
	.ENABL	LC
	.Sbttl	Author's Credits
 
;	Author:		??
;	Modified By:	Henry R. Tumblin
 
;	Date:		23-Jul-79

;	Version:	2.0
 
;	For:		Systems -- Utilities
 
;	Module Name:	VOLUME
 
;	Build File:	VOLUME.DCL
 
;	Residence:	[311,33]VOLUME.MAC
 
;	Machine/System:	PDP-11/70 IAS V3.0
 
;	Type/Language:	Main/Assembler
 
;	Abstract:	This program scans the Physical Unit Directory
;			for all mountable devices and displays their
;			status.
;
;	Edits:
;
;No.	Date	By	Reason
;--- ---------	------	--------------------------------------------
;+01 23-Jul-79	HRT	Re-write and other mods.
;+02 24-Jul-79	HRT	IAS V03.0 mods

	.SBTTL	LOCAL MACROS

	.MCALL	QIOW$,DIR$,EXST$S

;	MACROS USED
;
	.MACRO	PUSH,LIST
	.IRP	.I.,<LIST>
	.IF	IDN,<.I.>,<*>
	CLR	-(SP)
	.IFF
	MOV	.I.,-(SP)
	.ENDC
	.ENDR
	.ENDM

	.MACRO	POP,LIST
	.IRP	.I.,<LIST>
	.IF	IDN,<.I.>,<*>
	TST	(SP)+
	.IFF
	MOV	(SP)+,.I.
	.ENDC
	.ENDR
	.ENDM
 
	.MACRO	PRINT,.BUFF.,.LEN.,.CCW.
 
	MOV	.BUFF.,-(SP)
	MOV	.LEN.,-(SP)
	.IF	B	.CCW.
	CLR	-(SP)
	.IFF
	MOV	.CCW.,-(SP)
	.ENDC
	CALL	$OUT
	.ENDM

	.SBTTL	Equates and FDB's

LUN	=	1			;DISPLAY LINE LUN
FLAG	=	10.			;DISPLAY LINE EVENT FLAG

V.TRCT	=	0			; Count of users on volume
V.IFWI	=	2			; Index file window address
V.STD	=	4			; 
V.FCB	=	6			;
V.IBLB	=	12			; Start LBN of Index File Bitmap(high)
V.IBSZ	=	13			; Number of blocks in bitmap
V.FMAX	=	16			; Maximum number of files on volume
V.WISZ	=	20			; Window size
V.SBCL	=	21			; Storage bitmap cluster size
V.SBSZ	=	22			; Number of blocks in storage bitmap
V.SBLB	=	24			; Start LBN of Storage File Bitmap
V.FIEX	=	25			; Default file extension increment
V.FPRO	=	30			; Default file protection
V.FRBK	=	34			; Free blocks on device
V.LRUC	=	35			; Count of entries in directory LRU
V.LABL	=	40			; Volume label
V.STAT	=	54			;
	VC.IFW=1			;
	VC.BMW=2			;
V.FFNU	=	55			;
V.LGTH	=	56			;

V.LENG	=	12.			;VOLUME LABEL LENGTH
;
;	DIRECTIVES
;
$WRT:	QIOW$	IO.WLB,LUN,FLAG,100,,,<0,0,0>

IOSTAT:	.BLKW	2			;I/O STATUS BLOCK
FRBK:	.BLKW	2			; Free blocks on device

	.SBTTL	MESSAGES
 
MSGBUF:	.BLKB	133.			; +01 Message buffer
TMPBUF:	.BLKB	80.			; String building buffer

HEADR:	.ASCII	"Device"<11><11>"Status%N"
	.ASCII	"======"<11>
	.ASCIZ	<11>"============================================"

BASE:	.ASCIZ	"%2S%2A%O:"<11><11>"%VA"

REDR:	.ASCIZ	"is redirected to Device - %2A%O:"

OFFL:	.ASCIZ	"- Device handler is%VAresident, Controller is offline"

NOT:	.ASCII	" not "
	NOTS=.-NOT

FOR:	.ASCIZ	"is mounted [FOREIGN]%VA"

DMO:	.ASCIZ	" - Dismount pending"
	DMOS=.-DMO

VOF:	.ASCII	"- Volume is off-line"
	VOFS=.-VOF

BVCB:	.ASCIZ	"- Bad VCB extension detected"

MOU:	.ASCII	"- Volume '%VE' is mounted,%N"
	.ASCIZ	<11><11>"%4S%D users, %T blocks free"

	.EVEN

	.sbttl	Sample Pud
 
;	The following PUD is for test purposes only. This allows the
;	program to be tested without having to be built priviledged
;	and also prevents nasty system crashes.
 
;D$$BUG=1
	.IF	DF	D$$BUG
	.even
U.SZ=64
.PUDBA:	.WORD	PUD
.PUDEA:	.WORD	PUD+<U.SZ*2>
 
PUD:	.WORD	"HH
	.BYTE	0,200
	.WORD	100000+40000+10
	.BLKW	4.
	.WORD	PUD
	.BLKW	7.
	.WORD	VCB
	.BYTE	1,20
	.BYTE	0,0
	.BLKW	8.

	.WORD	"HH
	.BYTE	1,200
	.WORD	100000+40000+10
	.BLKW	4
	.WORD	PUD+64
	.BLKW	7
	.WORD	VCB
	.BYTE	1,20
	.BYTE	200+100,0
	.BLKW	8.

VCB:	.WORD	3			; Number of users
	.BLKB	32
	.BYTE	0,0
	.WORD	5000.
	.ASCII	"VOLUME LABEL"
	.WORD
	.ENDC

	.SBTTL	START MAINLINE CODE

;
;	INITIALIZATION
;
VOLUME:
 
;	Output the header line
 
	MOV	#MSGBUF,R0		; Point to output area
	MOV	#HEADR,R1		; Point to header line
	CLR	R2			; No argument list
	CALL	$EDMSG			; Format it
	PRINT	#MSGBUF,R1,#40		; Output to screen

;	Scan the PUD

	MOV	.PUDBA,R4		;SET THE START OF THE PUD TABLE

BGIN:	CMP	.PUDEA,R4		; +02 Are we at the end yet ?
	BNE	CHKRED			; +02 NE - no, display volume msg
 
	EXST$S	#EX$SUC			; +03 Exit with success

;	CHECK FOR PUD REDIRECTION

CHKRED:	MOV	R4,R5			;SET THE CURRENT PUD ADDRESS

 10$:	CMP	U.RP(R5),R5		;IF THE PUD IS REDIRECTED TO ITSELF,
	BEQ	CHKUC1			;THAT'S THE END OF THE REDIRECTION
	MOV	U.RP(R5),R5		;OTHERWISE, SET THE REDIRECTED PUD
	BR	10$			;ADDRESS AND CHECK IT FOR REDIRECTION

;	CHECK CHARACTERISTICS WORD 1

CHKUC1:	BIT	#UC.DIR,U.C1(R5)	;CHECK IF DEV IS DIRECTORY-STRUCTURED
	BEQ	10$			;EQ - then skip this pud
	BIT	#UC.MNT,U.C1(R5)	;CHECK IF DEVICE IS MOUNTABLE
	BEQ	10$			;EQ - then skip this pud
	BIT	#UC.F11,U.C1(R5)	;CHECK IF DEV IS FILES-11 STRUCTURED
	BNE	SETDV1			;NE - then this is valid device
10$:	JMP	NXTPUD			;IF ANY CHECK FAILS => NEXT PUD
;
;	SET THE DEVICE MESSAGE
;
SETDV1:	MOVB	U.UN(R4),R1		; +02 Get unit # -> R1
	MOV	R1,-(SP)		; +02 Set up as argument
	MOV	R4,-(SP)		; +02 Point to device name
	ADD	#U.DN,(SP)		; +02 Set up device name as arg.

;	At this point, the argument list for the basline message
;	has been initialized with the device name and unit number.
;	this info will remain on the stack until the entire message
;	has been built, then built via a final call to $EDMSG

	CMP	R4,R5			;CHECK FOR REDIRECTION
	BEQ	CHKUFB			;EQ - then no redirection
	MOVB	U.UN(R5),R1		; +02 Get unit # -> R1
;
;	Here we have found that the device has been redirected.
;	Display the device name to which it has been redirected.

	MOV	R1,-(SP)		; +02 Set up as argument
	MOV	R5,-(SP)		; +02 Point to device name
	ADD	#U.DN,(SP)		; +02 Set up device name as arg.
	MOV	#TMPBUF,R0		; +02 Point to build area
	MOV	#REDR,R1		; +02 Point to format string
	MOV	SP,R2			; +02 Point to argument list
 	CALL	$EDMSG			; +02 Create substring
	CMP	(SP)+,(SP)+		; +02 Clean up the stack
	CALL	OUTMSG			; +02 Output the message
	JMP	NXTPUD			; +02 Go do next PUD

	.sbttl	CHECK THE FLAGS BYTE

CHKUFB:	BITB	#UF.OFL,U.FB(R4)	;CHECK IF THE CONTROLLER IS OFF-LINE
	BEQ	CHKUCH			; EQ - then check characteristics

;	At this point, the controller is either offline, with the
;	device handler resident or non-resident.

	CLR	R1			; +02 Assume handler resident
	BITB	#UF.RH,U.FB(R4)		; Is the device handler resident ?
	BNE	10$			; NE - yup,
	MOV	#NOTS,R1		; +02 Set for NOT resident
10$:	MOV	#NOT,-(SP)		; +02 Set up message plist
	MOV	R1,-(SP)		; +02 Set string length
	MOV	#TMPBUF,R0		; +02 Point to build area
	MOV	#OFFL,R1		; +02 Point to format string
	MOV	SP,R2			; +02 Point to argument list
	CALL	$EDMSG			; +02 Format message
	CMP	(SP)+,(SP)+		; +02 Clean up the stack
	CALL	OUTMSG			; +02 Build and output message
	JMP	NXTPUD			; +02 Go check next device

	.sbttl	CHECK THE CHARACTERISTIC FLAGS BYTE

CHKUCH:	BITB	#CH.OFF,U.CH(R4)	;CHECK IF THE VOLUME IS OFF-LINE
	BEQ	10$			; EQ - nope, check next bit
	MOV	#VOFS,R1		; Get message size -> R1
	MOV	#TMPBUF,R2		; Point to destination -> R2
	MOV	#VOF,R0			; Get message pointer
	MOV	R1,-(SP)		; Save R1
5$:	MOVB	(R0)+,(R2)+		; Move into place
	SOB	R1,5$			; Loop till thru
	MOV	(SP)+,R1		; Restore R1
	CALL	OUTMSG			; Output the message
	BR	NXTPUD			; Go do next device

10$:	BITB	#CH.FOR,U.CH(R4)	;CHECK IF VOLUME IS MOUNTED AS FOREIGN
	BEQ	CHKVCB			; EQ - no, check VCB
	CLR	R1			; Set no DMO pending
	BITB	#CH.UNL,U.CH(R4)	;CHECK IF A DISMOUNT IS PENDING
	BEQ	12$			; EQ - then no dismount pending
	MOV	#DMOS,R1		; Set string length -> R1
12$:	MOV	#DMO,-(SP)		;  ...
	MOV	R1,-(SP)		; Set up parameter list
	MOV	#TMPBUF,R0		; Set up substring
	MOV	#FOR,R1			; Point to format string
	MOV	SP,R2			; Point to parameter list
	CALL	$EDMSG			; Edit the string
	CMP	(SP)+,(SP)+		; Clean up stack
	CALL	OUTMSG			; Output message
	BR	NXTPUD			; And do next pud

	.sbttl	EXTRACT THE MOUNT INFORMATION FROM THE VCB EXTENSION AREA
;
;	First make sure that the VCB is valid for this device

CHKVCB:	MOV	U.VA(R4),R5		;SET THE VCB EXTENSION ADDRESS
	BNE	GVCB			; NE - then valid VCB
	CLR	R1			; Set string length
	BITB	#CH.UNL,U.CH(R4)	; Is DMO pending ?
	BEQ	10$			; EQ - then not pending
	MOV	#DMOS,R1		; Else set length	
10$:	MOV	#DMO,-(SP)		; Point to the string
	MOV	R1,-(SP)		; Set it's length
	MOV	#TMPBUF,R0		; Point to output area
	MOV	#BVCB,R1		; Point to format string
	MOV	SP,R2			; Point to parameter list	
	CALL	$EDMSG			; And output message
	CMP	(SP)+,(SP)+		; Clean up stack
	CALL	OUTMSG			; Output the message
	BR	NXTPUD			; And go check the next device

;	Now display the number of users of this volume
 

GVCB:
	MOVB	V.FRBK(R5),FRBK		; Get total free blocks on device
	MOV	V.FRBK+2(R5),FRBK+2	;   ...
	MOV	#FRBK,-(SP)		; Point to doubleword
	MOV	V.TRCT(R5),-(SP)	; Get # of users -> R1
	MOV	R5,-(SP)		; Get pointer to
	ADD	#V.LABL,(SP)		;  Volume Label
	MOV	#V.LENG,-(SP)		; Get length of volume label
	MOV	#TMPBUF,R0		; Point to output area
	MOV	#MOU,R1			; Point to format string
	MOV	SP,R2			; Point to parameter list	
	CALL	$EDMSG			; And output message
	ADD	#10,SP			; Clean up stack
	CALL	OUTMSG			; Output the message
	BR	NXTPUD			; And go do next pud

;	ADVANCE TO THE NEXT PUD
;
NXTPUD:	ADD	#U.SZ,R4		;POINT AT THE NEXT PUD ENTRY
	JMP	BGIN			; Go check next PUD

	.sbttl	Support Subroutines
	.sbttl	1) OUTMSG -- Output Baseline Message
 
;	This subroutine will build and output the baseline message
;	string to TO:. 
 
;	Inputs:
 
;		R1 -- Length of substring to insert in baseline string

;	       (SP)-- RETURN ADDRESS
;	      2(SP)-- Device Name
;	      4(SP)-- Device Unit Number
;	     TMPBUF-- The substring to insert
 
OUTMSG:	CMP	-(SP),-(SP)		; +02 Create two entries on stack
	MOV	4(SP),(SP)		; +02 Correct return address
	MOV	10(SP),4(SP)		; +02 Get unit #
	MOV	6(SP),2(SP)		; +02 Get device name
	MOV	R1,6(SP)		; +02 Set character count
	MOV	#TMPBUF,10(SP)		; +02 Point to temp string
	MOV	#MSGBUF,R0		; +02 Point to output buffer
	MOV	#BASE,R1		; +02 Point to baseline message
	MOV	SP,R2			; +02 Point to parameter list
	ADD	#2,R2			; +02 ...+2
	CALL	$EDMSG			; +02 Format message
	PRINT	#MSGBUF,R1,#40		; +02 Output message
	MOV	(SP),10(SP)		; +02 Restore return address
	ADD	#10,SP			; +02 Clean up the stack
	RETURN				; +02 Return to calling proc.


	.sbttl	2) $OUT	--	Output line to TO:
 
;	This subroutine will output a string to the terminal 
;	that is currently assigned to TO:
 
$OUT:	MOV	4(SP),$WRT+Q.IOPL+2	; Set buffer length
	BEQ	10$			; EQ - then skip I/O
	MOV	2(SP),$WRT+Q.IOPL+4	; Set CCW word
	MOV	6(SP),$WRT+Q.IOPL	; Set buffer address
	DIR$	#$WRT			; Perform I/O
10$:	MOV	(SP),6(SP)		; Restore return address
	ADD	#6,SP			; Clean up stack
	RETURN				; Return to whom called us

	.END	VOLUME
