/*static char *SCCSID = "@(#)cachread.c	6.4 91/10/30";*/

#define SCCSID "@(#)cachread.c	6.4 91/10/30"
/********************************************************/
/*                                                      */
/*       IBM/Microsoft Confidential                     */
/*                                                      */
/*       Copyright (c) IBM Corporation 1987, 1989       */
/*       Copyright (c) Microsoft Corporation 1987, 1989 */
/*                                                      */
/*       All Rights Reserved                            */
/********************************************************/

#define FNO_NUM FNO_CACHREAD_C
#define INCL_TYPES                      // for basedef.h typedefs
#include <osconst.h>
#include <ostypes.h>
#include <fnofs.h>
#include <osmac.h>
#include <basemac.h>
#include <basedef.h>
#include <mi.h>
#include <vmexport.h>
#include <selxport.h>
#include <pgexport.h>
#include <tkexport.h>
#include <smexport.h>
#include <sft.h>
#include <cache.h>
#include <string.h>


/***EP  BufAlloc - Buffer Allocate
 *
 *
 *      ENTRY  rba         = relative block address
 *             hVPB        = Handle to volume
 *      EXIT:  pBuf        = pointer to new buffer header
 *
 *      WARNING:
 *
 */
PBUFHDR BufAlloc(rba,hVPB)
ulong_t  rba;
ulong_t hVPB;
{
register PBUFHDR pBuf;

      // round rba down to a multiple of SectorsPerPage

      rba = ROUNDRBA(rba);

      pBuf = GFB(GFB_BLOCK);
      pBuf->BufDirtyMsk = 0;
      pBuf->BufFileDirtyMsk = 0;
      pBuf->BufRBA = rba;
      pBuf->BufDirtyLru.pbufFwd = NULL;
      pBuf->BufhVPB = hVPB;
      pBuf->BufFlag = NULL;
      return(pBuf);
}

/***EP  BufFind - Buf Find
 *
 *
 *      ENTRY  rba         = relative block address
 *             flags       = flags
 *             hVPB        = Handle to volume
 *      EXIT:
 *
 *      WARNING:
 *
 */
PBUFHDR BufFind(rba,flags,hVPB)
ulong_t  rba;
ulong_t flags;
ulong_t hVPB;
{
register  PBUFHDR pBuf;
int rc,fMustRead;

      // round rba down to a multiple of SecPerBuf

      rba = ROUNDRBA(rba);

      for (;;) {
         pBuf = CCH(rba,hVPB);
         if (pBuf != NULL){
            if (pBuf->BufFlag & BUF_LOCK) {
               BufWaitUnLock(pBuf);
            }
            else {
               rc = 0;
               if (flags == BFND_READ){
                  if (pBuf->BufFlag & BUF_LAZYREAD){

                     // This is for a read request and the LAZYREAD flag is
                     // set. If the buffer is clean, lets put it on the
                     // free list rather than reading it off the disk and
                     // traversing through the bit map.

                     if ((pBuf->BufDirtyMsk == 0)  &&
                         (pBuf->BufDirtyLru.pbufFwd == NULL) &&
                         (!(pBuf->BufFlag & BUF_LWLOCK)) &&
                         (pBuf->BufRefCnt == 0)){

                        BufUnlink(pBuf);
                        BufFree(pBuf);
                        rc = TRUE;
                     }
                     else {
                        rc = LazyRead(pBuf,
                                      NULL,
                                      SSToDS(&fMustRead));
                        rc = TRUE;
                     }
                  }
               }
               if (!rc) {
                  PlaceBuf(pBuf,PLCBUF_MRU);
                  return (pBuf);
               }
            }
         }
         else
            return (NULL);
      }
}
