	.title	FRESPC -- Check free space left on disk.
	.enable	lc



;	Copyright (C) 1983	American Newspaper Publishers Association
;				11600 Sunrise Valley Drive
;				Reston, Virginia  22091



	.ident		/02/

;	Written:	1 February 1983
;			John P. McGrath


;	FORTRAN callable routine to check if there is a given amount
;	of free disk space left.
;
;		CALL FRESPC(LUN, MIN, RESULT)
;
;		    LUN =	Logical unit assigned to the test device.
;		    MIN =	Disk space required.
;		    RESULT =	Result of test.
;					<0 = error
;					 0 = more than MIN blocks free.
;					>0 = only RESULT blocks free.
;
;	The logical unit number (LUN) may be associated with the device
;	using any of several different methods.  These include the task
;	builder ASG= option and the ASSIGN subroutine.  If the ASSIGN
;	subroutine is used, then the UFD named in the call must exist.
;	If it is not certain that there will be a UFD for the current
;	UIC on the device specified, an explicit UIC should be specified.
;	Since all disks must have a [0,0] directory, it is safe to use
;	[0,0].
;
;	example:
;			CALL ASSIGN(2, 'XY1:[0,0]')
;			CALL CHKFRE(2, 1000, RESULT)
;
;	Note that MIN can only take a value up to 32767.  The exact 
;	amount of free space (up to 32767 blocks) can be determined
;	by setting MIN to 32767.
	.page
	.mcall	dir$,alun$,glun$,qiow$
	.mcall	fdbdf$,fdrc$a,fdbk$a,fdop$a,open$r,close$r

	.globl	FRESPC


fdb:	fdbdf$
	fdrc$a	fd.rwm
	fdbk$a	buf,512,.,,10
	fdop$a	0,dsd

dsd:	.word	0,0
	.word	uicsiz,uic
	.word	namsiz,name

uic:	.ascii	/[0,0]/
uicsiz	=	.-uic

name:	.ascii	/BITMAP.SYS/
namsiz	=	.-name

	.even


read:	qiow$	io.rvb,0,10,,iost,,<buf,512.,,,1>

iost:	.word	2

buf:	.blkb	512.
endbuf	=	.


glun:	glun$	0,gbuf			; get lun info
gbuf:	.blkw	6			;   (to check for files-11 device)


blknum:	.word	1			; current block in BITMAP.SYS
blkcnt:	.word	1			; number of free blocks found
maxblk:	.word	1			; number of blocks to look for
	.page
FRESPC:
	mov	@2(r5),read+q.iolu	; set LUN in read DPB
	movb	@2(r5),fdb+f.lun	; set LUN in FDB
	mov	@2(r5),glun+g.lulu	; set LUN in get-lun-info DPB

	dir$	#glun			; get LUN info
	bcs	err1			; error

	bit	#40000,g.lucw+gbuf	; mountable files-11 device?
	beq	err2			; no


	mov	@4(r5),maxblk		; get maximum blocks to count
	mov	#1,blknum		; start with block 2
	clr	blkcnt

	open$r	#fdb			; open BITMAP.SYS
	bcs	err3			; if open failure

block:
	inc	blknum
	mov	blknum,read+q.iopl+10	; set block number to read
	dir$	#read			; read block
	tstb	iost
	blt	eoftst			; if error in read (possibly EOF)
	mov	#buf,r0			; start of buffer

word:
	mov	(r0)+,r1		; get next word
	beq	50$			; if all blocks used
	cmp	#-1,r1			; are all blocks empty?
	bne	10$			; no - count the bits
	mov	#16.,r2			; yes - 16 blocks free
	br	40$			; add to count
10$:
	clr	r2			; zero bit count
	mov	#16.,r3			; number of bits to check
20$:
	asr	r1			; is bit set?
	bcc	30$			; yes - block is used
	inc	r2			; no - block is free
30$:
	dec	r3			; bit counter
	bne	20$			; check next bit
40$:
	add	r2,blkcnt		; add bits in this word to total
	mov	blkcnt,r3
	cmp	blkcnt,maxblk		; have we found enough free blocks?
	bhi	enough			; yes
50$:
	cmp	r0,#endbuf		; have we exausted buffer?
	blo	word			; no - do next word
	br	block			; yes - do next block
	.page
enough:					; we have found enough free blocks
	clr	r1			; zero return value indicates OK
	br	exit			; return

eoftst:
	cmpb	#ie.eof,iost		; did we hit EOF
	bne	err4			; no - some other error
	mov	blkcnt,r1		; yes - set return value to block count
	br	exit			; return


err1:
	mov	#-1,r1
	br	exit

err2:
	mov	#-2,r1
	br	exit

err3:
	mov	#-3,r1
	br	exit

err4:
	mov	#-4,r1
	br	exit



;	R1 contains return value:
;
;		< 0  =	Error reading bitmap file.
;		  0  =	Greater than MAXBLK free blocks found.
;	  1..MAXBLK  =	indicates number of blocks found <= MAXBLK

exit:
	close$r	#fdb			; close BITMAP.SYS
	mov	r1,@6(r5)		; set return value
	rts	pc			; back to calling program


	.end
