/*static char *SCCSID = "@(#)lsd.c	6.2 92/01/31";*/
#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include <pvwxport.h>
#include "const.h"
#include "pbmacros.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "storage.h"
#include "tables.h"
#include "assert.h"
#include "lw.h"
#include "log.h"
#include "frame.h"
#include "fsdata.h"
#include "pvw.h"

#include "pr_CACHE.h"
#include "pr_DEBUG.h"
#include "pr_MISC.h"

/*
 ***	LSD - Locate Sector Data
 *
 *	LSD locates a sector of data in the buffer cache.
 *
 *	LSD is passed the address of SECPTR structure, which
 *	contains the sector number and an advisory pointer to
 *	a buffer header.  That pointer probably points to the
 *	header of the buffer that contains the sector.  If it
 *	does, we return quickly with the address of the sector's
 *	data itself.  If not, we locate the sector in the cache
 *	and read it in, if we must.
 *
 *	In any case, if the cache block is locked then we
 *	wait for it to unlock.
 *
 *	ENTRY	pscpDesired = address of SECPTR structure for
 *				desired sector
 *				(contains Vsector)
 *		priBuf = Bits0-14 : Where does it belong in LRU chain?
 *			 Bit15: Set - Do error checking for LSDDB().
 *
 *	EXIT	NOTE - we always return *ppbuf, so error processing works
 *		*ppbuf = address of the buffer header
 *		*pscpDesired may be updated
 *		Returns pointer to the sector (if ok)
 *		Returns NULL if error
 *
 *	HISTORY
 *	    21-Sep-1988 09:15:54 by Bill McJohn [t-billm]
 *				brought up to date with 9/15/88 assembly code
 */

PVOID
LSD (pscpDesired, priBuf, ppbuf, pfrm)
PSECPTR		pscpDesired;	/* pointer to desired sector/hint pair */
USHORT		priBuf;		/* where does it belong in LRU chain?  */
PBUFNODE far	*ppbuf;		/* pointer to the PBUFNODE for desired sector */
PFRAME		pfrm;
{
    PSECTOR psec;
    register PBUFNODE pbuf;
    LSN lsn;

#ifdef DEBUG2
    ChkHashChain ();
#endif

    ASSERT_SECPTR (pscpDesired);

#ifdef BUFZAP
    DoZap();
#endif

#ifdef PERFVIEW
    PVWINC(Ca,BHints); /* Increment count of hints used */
#endif

    pbuf = pscpDesired->pbufHint;

	 lsn = pscpDesired->lsn & SECMASK; /* zero out volume bits */

    lsn |= pfrm->pvol->ulVolBits; /* get volume bits */

    while (TRUE) {

	/* if the hint is invalid, read the bitmap sector */
	if ((pbuf == NULL) ||
	    ((lsn & ~(ULONG)SPBMASK) != pbuf->lsnSec) ) {  //@82290

	    /*	No hint buffer OR buffer contains other data
	     *	we must rebuffer the sector and update the hint
	     */
                                                     //@82290
	    if ((psec = RdBuf (lsn,
			       priBuf & ~LSDBM_FLAG,
			       ppbuf, pfrm)) == NULL) {
		/* hard error, *ppbuf has been updated by RdBuf */
         return NULL;
	    }

       pbuf = *ppbuf;

	    /*	correct the hint  */
	    pscpDesired->pbufHint = pbuf;

	    /*
	     * If the call was LSD for a bitmap sector, then do a
	     * special check for errors.
	     */
	    if (priBuf & LSDBM_FLAG) {

//   		pbuf->fFlag |= BFL_BITMAP;
	   	if (pbuf->bBadMask) {
		     LSDBMError(pbuf,pfrm);
	   	}
	    } else {
//#114986
#ifndef MINIFSD
        if (pbuf->fFlag & BFL_LZREAD) {
          if (LazyRead (pbuf, pfrm))
            return NULL;
        }
#endif
       }

	    return psec;
	}

	/* if the locked bit is off it is okay to check out the sector */
	if (pbuf->cLocked == 0) {

//#114986
#ifndef MINIFSD
     if (pbuf->fFlag & BFL_LZREAD) {
       if (LazyRead (pbuf, pfrm))
         return NULL;
     }
#endif

	    PlaceBuf (*ppbuf = pbuf, priBuf & ~LSDBM_FLAG);

	    /*
	     * If the bad mask bit is on for the desired sector, then we
	     * got a hard error.
	     */
	    if (((1 << (lsn & SPBMASK)) & pbuf->bBadMask) != 0) {

		 /* sector has error */
		   SETHARDERR (ERROR_READ_FAULT);

		 /* *ppbuf was set above */
		   return NULL;
	    }
#ifdef PERFVIEW
	    PVWINC(Ca,BHits); /* The hint was good */
#endif
                                                                      //82290
       return ((PSECTOR) (pbuf->pblkData)) + (lsn & (ULONG)SPBMASK);

	}
	else {
	    /* Sector is not free */
	    WBU (pbuf,pfrm);
	}
    }
}
