/*static char *SCCSID = "@(#)choosedb.c	6.2 92/01/31";*/
#define BSWAP2 BSWAP2
#include <os2.h>
#include "api.h"
#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "storage.h"
#include "fnode.h"
#include "tables.h"
#include "pb_ifs.h"
#include "superb.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "pbmacros.h"

#include "pr_ALLOC.h"
#include "pr_BITMP.h"
#include "pr_CACHE.h"


/*
 ***	ChooseDB - Choose DirBlk Location
 *
 *	ChooseDB is called when a new directory is created.  It returns
 *	a sector number in the DIRBLK reserved area which we feel is
 *	a good area to pioneer.  Basically, we look for multiple available
 *	sectors so that our future DIRBLKs will probably be close together.
 *
 *	ENTRY	none
 *	RETURNS (eax) = DIRBLK sector number. This is the sector to be "near
 *			to", it is not guaranteed to be available!
 *
 *
 *	HISTORY
 *	    24-Oct-1988 02:30 by Bill McJohn [t-billm]
 *				Translated from 10/21/88 assembly code
 */
LSN
ChooseDB(PFRAME pfrm)
{

	PBUFNODE pbufMap;	/*  Just used for call to LSD  */
	PBANDTAB pbtdb;		/*  to speed up access to db band table */
	PBYTE pbStart, pbCur, pbBest;
	ULONG ulOff;
	BYTE bBest = 0;

	/*  If there aren't any free DIRBLKS in the DIRBLK
	 *  band, don't even bother looking.
	 */
	pbtdb = &pfrm->pvol->bndDirBand;
	if (pbtdb->csecFree == 0) {
		/* none available - just say 0 */
		return(0L);
	}


	/*  Find the beginning of the DIRBLK bitmap  */
                                                                //#85759
	if ((pbStart = (PBYTE) LSDBM(&pbtdb->scpMap, BP_KEEP, &pbufMap, pfrm)) == NULL)
     return(0L);

	/*  Scan forward looking for the first byte with the
	 *  greatest number of free bits.  If we find an FF
	 *  byte, we stop, since that's the best we could
	 *  possibly do.
	 *
	 */
	pbBest = pbStart;

	for (ulOff = 0, pbCur = pbStart;
	     ulOff < pbtdb->cbMapLen;
	     ulOff++, pbCur++) {

	    if (*pbCur == 0xFF) {
		pbBest = pbCur;
		break;
	    }

	    if (abCont[*pbCur] > bBest) {
		pbBest = pbCur;
		bBest = abCont[*pbCur];
	    }
	}


	/*  pbBest now points at the best byte we could find.
	 *  Note that bits in the DIRBLK bitmap correspond
	 *  to DIRBLKS, not sectors, so we must convert back
	 *  to sectors (multiply by DIRBLKS/SECSIZE)
	 */

	return (pbtdb->lsnBase +
			8 * (pbBest - pbStart) * (DIRBLKS/SECSIZE) );

}
