/*static char *SCCSID = "@(#)adb.c	6.1 90/11/17";*/
/*static char *SCCSID = "@(#)adb.c	13.3 90/01/25";*/
#define ASWAP1 ASWAP1
#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 "lw.h"
#include "frame.h"
#include "fsdata.h"

#include "pr_BITMP.h"

#ifdef DEBUG
#include "pr_MISC.h"
#endif


/*
 ***	ADB - Allocate Directory Block
 *
 *	ADB is a captive of AllocDB.  It scans in the specified
 *	direction looking for 4 free sectors on a multiple of four
 *	boundary (DIRBLKS are 4 sectors while cache blocks are each SPB
 *      sectors, a DIRBLK will allways be either in the first half or in
 *      the second half of a cache block.)
 *
 *	ENTRY	cBMLeft = length of bit map left
 *		fBkwd = 0 if forward scan, 1 if backwards scan
 *		pbBitMap = pointer to bitmap bits to scan
 *
 *	EXIT	Returns FALSE if couldn't find the bits
 *		Returns TRUE if bits found
 *		  bits not removed from map
 *		  *pbLowestBit = bit index of lowest bit (modulo 8)
 *		  *poffulFoundAdr = index of map byte which contained bits
 */


BOOL
ADB (cBMLeft, fBkwd, pbBitMap, pbLowestBit, poffulFoundAdr)
USHORT cBMLeft;		/* length of bit map left */
BOOL fBkwd;		/* true if backward scan, false if forward scan */
PBYTE pbBitMap;		/* pointer to bitmap to scan */
PBYTE  pbLowestBit;	/* bit index of lowest bit (mod 8) */
PULONG poffulFoundAdr;	/* index of map byte which contained bits */
{
    register USHORT i;		/* Search index */
    register USHORT cBytes;	/* Number of bytes to scan */
    SHORT	sInc;		/* Direction increment */
    BYTE	iBit = 8;	/* bit index for alignment */

#ifdef DEBUG
    if (cBMLeft > SPB * SECSIZE)
	INTERR ("ADB: cBMLeft too big");
#endif

    /* Get starting and stopping indecies */
    i = 0;
    cBytes = cBMLeft;

    sInc = fBkwd ? (-1) : 1;


    do {
	/* search for 4 consecutive bits set */
	while( cBytes && abCont[ (int)pbBitMap[i] ] < (DIRBLKS/SECSIZE) ) {
	    i += sInc;
	    cBytes--;
	}

	/* if we didn't find any, then return failure */
	if( cBytes == 0 )
	    return FALSE;

	/* See if either all four high or all four low order bits
	 * are set.
	 */

#if DIRBLKS != 4 * SECSIZE
#error ADB:  DIRBLK is not 4 sectors
#endif


	if ( (pbBitMap[i] & 0x0F) == 0x0F ) {

	    /*	All four low-order bits are available, so
	     *	use four bits starting at bit zero.
	     */
	    iBit = 0;
	} else if ( (pbBitMap[i] & 0xF0) == 0xF0 ) {

	    /*	All four high-order bits are available, so
	     *	use four bits starting at bit four.
	     *
	     */
	    iBit = 4;
	} else {

	    /*	Can't use this byte.  Carry on. */
	    i += sInc;
	    cBytes--;
	}

    } while( iBit >= 8 );

    /* We found them, so return their position */
    *pbLowestBit = iBit;
    *poffulFoundAdr = i;

    return TRUE;
}
