/*static char *SCCSID = "@(#)vbr.c	6.2 92/01/31";*/
#define ASWAP0 ASWAP0

#include <os2.h>
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "volume.h"
#include "tables.h"
#include "superb.h"
#include "pb_ifs.h"
#include "pbmacros.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"

#include "pr_BITMP.h"
#include "pr_CACHE.h"
#include "pr_MISC.h"


/***	VBR - Verify Bit Run Length
 *
 *	VBR verifies that the desired number of one bits are
 *	available at the specified bit position.
 *
 *	VBR is called to see if we can do a contiguous allocation,
 *	so it's goal is to verify the one bits as quickly as it can.
 *	Many requests will be comparitively small, so we have
 *	some special sequences for those cases.
 *
 *	Note that we don't have to worry about running off the
 *	end of the bitmap, since all bitmaps end with at least
 *	one 00 byte; we'll see those zeros and quit.
 *
 *	ENTRY	cusGoalBitNum = number of bits that we're looking for
 *		ulCheckPt = first bit to investigate
 *
 *	EXIT	Returns TRUE if bits available
 *			FALSE if bits unavailable
 *
 *	HISTORY
 *	    23-Aug-1988 17:49:54 by Jon Parati [jonpa]	Copied from CBR.C
 *	    05-Oct-1988 16:44:55 by Jon Parati [jonpa]	Copied from CBR.C
 */

BOOL
VBR (cusGoalBitNum, ulCheckPt, pfrm)
USHORT cusGoalBitNum;	/* number of bits we're looking for */
ULONG ulCheckPt;	/* index of BIT to start checking from IN THE BITMAP */
PFRAME pfrm;
{
    register USHORT i;	/* index */
    register USHORT cb; /* count of bits */
    PBYTE pb;		/* pointer into bitmap bits */
    BYTE bFirstBit;	/* bit index of first bit */
    PBANDTAB pbtb;
    PBUFNODE pbuf;


#ifdef DEBUG
    if( ulCheckPt > pfrm->pvol->cSectsOnVol )
	INTERR( "vbr: starting sector not on volume" );
#endif

    if( ulCheckPt == pfrm->pvol->cSectsOnVol )
	/* Last file sector is last volume sector */
	return FALSE;

    /* Initialize vars */
    pbtb = pfrm->pvol->apbndList [USSHIFTRUL (ulCheckPt, BANDSHIFT)];
    i = (USHORT)(ulCheckPt % BANDSIZE);
    bFirstBit = (BYTE)(i % 8);
    i /= 8;

    /*
     * Make sure we are not trying to count more than 1 band worth
     * of sectors.
     *
     * i = index of first byte to check in the band
     * cusGoalBitNum = number of BITS to count
     * pbtb->culMapLen = length of band in BYTES
     */
    if( i + ((cusGoalBitNum + 7) / 8) > pbtb->cbMapLen )
	return FALSE;

    /*
     * Load the bandtab
     */

    /* DEBUG - This is a good place for statistical stuff */
    if ((pb = LSDBM(&pbtb->scpMap,
		    BP_KEEP,
		    &pbuf, pfrm)) == NULL) {
	return FALSE;
    }

    pb = &pb[i];


    /* check if first byte goes on into next byte */
    if( (cb = abRCont[*pb]) >= (8 - bFirstBit) ) {

	/*
	 * run spans more than 1 byte
	 */
	if( cb >= cusGoalBitNum )
	    return TRUE;

	/* Count the number of filled bytes */
	/* BUGBUG - Gordon's code does not check for running off of
	 *	    bitmap, but we will since it is not that much
	 *	    of a runtime hit
	 */
	pb++;
	for( i = pbtb->cbMapLen -i -1; i != 0 && *pb == 0xFF; i-- ) {
	    pb++;
	    if( (cb += 8) >= cusGoalBitNum )
		return TRUE;
	}

	if( i ) {
	    /* still on the bitmap so count the bits in the last byte */
	    cb += abLCont[*pb];
	}

	return	cb >= cusGoalBitNum;

    } else {

	/*
	 * run contained in first byte
	 *
	 * NOTE: bits are numbered 01234567 so "LeftCont" means
	 * contiguouse from bit 0 upward.  Therefore we must
	 * use a '>>' to shift to what Gordon calls LEFT.
	 */
	return (USHORT)abLCont[ *pb >> bFirstBit ] >= cusGoalBitNum;
    }
}
