/*static char *SCCSID = "@(#)cachinit.c 6.7 91/12/02";*/

#define SCCSID "@(#)cachinit.c  6.7 91/12/02"
/********************************************************/
/*                                                      */
/*       IBM/Microsoft Confidential                     */
/*                                                      */
/*       Copyright (c) IBM Corporation 1987, 1989       */
/*       Copyright (c) Microsoft Corporation 1987, 1989 */
/*                                                      */
/*       All Rights Reserved                            */
/********************************************************/
/******************************************************************************/
/*  7/22/94  Change Team  Defect 76643                                        */
/*           The method of allocating Fat Cache was changed.  If the user     */
/*           asks to allocate more than LOWMEM_MAXCACHE of Fat Cache, only    */
/*           LOWMEM_MAXCACHE worth of cache will be allocated initially.      */
/*           The system will then load the device drivers and determine if    */
/*           all of the PDDs support > 16MB.  The system will then initialize */
/*           high memory (if any).  Finally, FinishBufInit will be called     */
/*           to allocate the rest of the Fat Cache.  The system will allocate */
/*           the cache in high memory if all device drivers support it.  If   */
/*           the allocation fails, the init code will display an error and    */
/*           prompt the user to hit enter.                                    */
/******************************************************************************/

#define FNO_NUM FNO_CACHINIT_C
#define INCL_TYPES                      // for basedef.h typedefs
#include <osconst.h>
#include <ostypes.h>
#include <basemac.h>
#include <basedef.h>
#include <fnofs.h>
#include <osmac.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 <vmowner.h>

extern ulong_t cachebuffer1;
extern ulong_t cachebuffer2;
extern ulong_t cachebuffer3;
extern ulong_t cachebuffer4;
extern BYTE    FATCache;
extern BYTE    Defaultcache;
extern BYTE    fatvolume;



extern ulong_t CacheToAlloc;           //76643
extern unsigned char DDwith24BitDMA;   //76643

/* the percent dirty that the dirty chain has to get before it gets flushed */
// #83844
#define PERCENT_DIRTY_THRESH    80

#define LOWMEM_MAXCACHE 0x100000       //76643 - 1MB Cache

#pragma code_seg("CINIT_TEXT", "CODE")

/***EP  BufInit - initializes data for the FAT Buffers
 *
 *      Initialize data structures for FAT Buffers
 *
 *      ENTRY   cbBUFPAGESIZE  buffer size
 *
 *      EXIT    data structures initialized
 */

int    BufInit(CFGBUFPAGESIZE)
ulong_t CFGBUFPAGESIZE;
{

    VMAC                ac;             /* VMAllocMem I/O packet */
    PBYTE               pBufs;
    int                 i,j,rc;
    PBUFHDR             pBufInit;
    ulong_t             cbBufHdrSize;

        KSEMInit((HKSEM)&HotFixKsem, KRNL_MUTEXSEM, NA);
        KSEMInit((HKSEM)&FLWKsem, KRNL_MUTEXSEM, NA);
        CFGBUFPAGESIZE += CFGBUFPAGESIZE % BUFPAGESIZE;

        /* Only allocate LOWMEM_MAXCACHE worth of cache initially -76643*/
        if (CFGBUFPAGESIZE > LOWMEM_MAXCACHE)                    /*76643*/
        {                                                        /*76643*/
           CacheToAlloc   = CFGBUFPAGESIZE - LOWMEM_MAXCACHE;    /*76643*/
           CFGBUFPAGESIZE = LOWMEM_MAXCACHE;                     /*76643*/
        }                                                        /*76643*/

        if ((rc = VMAllocMem(CFGBUFPAGESIZE,
                                        /* Virtual size */
          CFGBUFPAGESIZE,
                                        /* Committed size */
          VMAC_LOCANY | VMAC_ARENASYS |
          PG_RESIDENT | PG_R | PG_W | PG_ZEROFILL,
          HOBNULL,
          FSBUFOWNER,
          HOBNULL,
          NULL,
          NULL,
          SSToDS(&ac))) != 0)           /* Virtual address */
          return(rc);                 /* Allocate the segment */

        cachebuffer1 = pBufs = (PBYTE)ac.ac_va;
        cBufs = CFGBUFPAGESIZE / (ushort_t)BUFPAGESIZE;
        /* set the LW threshold for number of buffs dirty before writing */
        LWData.cbufDirtyMax = (cBufs * (PERCENT_DIRTY_THRESH / 10)) /
                              (100 / 10);
//        LWData.cbufDirtyMax = 16;
        cbBufHdrSize = cBufs * sizeof(BUFHDR);
        if ((rc = VMAllocMem(cbBufHdrSize,
                                        /* Virtual size */
          cbBufHdrSize,
                                        /* Committed size */
          VMAC_LOCANY | VMAC_ARENASYS |
          PG_RESIDENT | PG_R | PG_W | PG_ZEROFILL,
          HOBNULL,
          FSBUFOWNER,
          HOBNULL,
          NULL,
          NULL,
          SSToDS(&ac))) != 0)    /* Virtual address */
            return(rc);                 /* Allocate the segment */
       cachebuffer2 = pBufInit = (PBUFHDR)ac.ac_va;


        // put all pages onto free list

        BufFreeList.BufFreeLru.pbufFwd = BufFreeList.BufFreeLru.pbufBak = &BufFreeList;
        BufLRUHead.BufLru.pbufFwd = BufLRUHead.BufLru.pbufBak = &BufLRUHead;
        BufDirtyHead.BufDirtyLru.pbufFwd =
                       BufDirtyHead.BufDirtyLru.pbufBak = &BufDirtyHead;

        for (j=0;j < cBufs;++j){
             pBufInit->BufLinAddr = pBufs;
             if (rc = VMLinToPhys((ulong_t)pBufs,
                                 (ulong_t *)(&pBufInit->BufPhysAddr)))
                return (rc);

             pBufs += BUFPAGESIZE;
             pBufInit->BufDirtyLru.pbufFwd = NULL;                                       \
             pBufInit->BufDirtyLru.pbufBak = NULL;                                       \

             pBufInit->BufLru.pbufFwd = pBufInit;                                       \
             pBufInit->BufLru.pbufBak = pBufInit;                                       \

            /* set forward and backward lru pointers */
            DCADDF (pBufInit, BufFreeLru, BufFreeList);
            ++pBufInit;
            ++FreeBufs;
        }
        if (rc = SELAllocKHB(VM_HKRH_PUBRW,S2_RW_RQPKT_SIZE,PG_CONTIG,0,FSBUFOWNER,SSToDS(&ac)))
           panic ("BufInit: Cannot allocate 512 contiguous memory");
        FLWReqListSel = (ulong_t)ac.ac_sel;
        return(0);
}


/***EP  FinishBufInit - Completes initialization of data for the FAT Buffers
 *
 *      Completes initialization of data structures for FAT Buffers
 *
 *      ENTRY   None
 *
 *      EXIT    data structures reinitialized if cache to alloc
 *              cache to alloc is linked into initially allocated initially
 *              CacheToAlloc == 0 if no error occurred
 *
 *      Created by defect 76643
 */

void  FinishBufInit()
{
    VMAC                ac;             /* VMAllocMem I/O packet */
    PBYTE               pBufs;
    int                 j,rc;
    PBUFHDR             pBufInit;
    ulong_t             cbBufHdrSize;
    ulong_t             tmp_cBufs;
    ulong_t             flags = VMAC_LOCANY | VMAC_ARENASYS |
                                PG_RESIDENT | PG_R | PG_W | PG_ZEROFILL;

    if (CacheToAlloc)
    {
       if (DDwith24BitDMA)
       {
          /* Device Drivers do not support memory above 16MB */
          flags |= PG_16M;
       }

       if (!(rc = VMAllocMem(CacheToAlloc,
                             CacheToAlloc,
                             flags,
                             HOBNULL,
                             FSBUFOWNER,
                             HOBNULL,
                             NULL,
                             NULL,
                             SSToDS(&ac))) != 0)
       {
          cachebuffer3 = pBufs = (PBYTE)ac.ac_va;
          tmp_cBufs = CacheToAlloc / (ushort_t)BUFPAGESIZE;
          cbBufHdrSize = tmp_cBufs * sizeof(BUFHDR);

          if ((rc = VMAllocMem(cbBufHdrSize,
                               cbBufHdrSize,
                               VMAC_LOCANY | VMAC_ARENASYS |
                               PG_RESIDENT | PG_R | PG_W | PG_ZEROFILL,
                               HOBNULL,
                               FSBUFOWNER,
                               HOBNULL,
                               NULL,
                               NULL,
                               SSToDS(&ac))) != 0)    /* Virtual address */
          {
             /* Unable to allocate BufHdr, so free the cache.  The user will
                be notified since CacheToAlloc is not cleared. */
             cachebuffer3 = 0;
             VMFreeMem((ulong_t)pBufs,HOBNULL,0);
             return;
          }

          cBufs += tmp_cBufs;
          LWData.cbufDirtyMax = (cBufs * (PERCENT_DIRTY_THRESH/10)) / (100/10);

          cachebuffer4 = pBufInit = (PBUFHDR)ac.ac_va;

          for (j=0;j < tmp_cBufs;++j)
          {
             pBufInit->BufLinAddr = pBufs;
             if (rc = VMLinToPhys((ulong_t)pBufs,
                                 (ulong_t *)(&pBufInit->BufPhysAddr)))
             {
                /* If we fail here, just return.  We may or may not have
                   linked all of the cache together depending upon the
                   iteration of "j".  Worst case, we don't get all of the
                   cache.  We will tell the user about this since CacheToAlloc
                   will not be cleared. */
                return;
             }
             pBufs += BUFPAGESIZE;
             pBufInit->BufDirtyLru.pbufFwd = NULL;
             pBufInit->BufDirtyLru.pbufBak = NULL;

             pBufInit->BufLru.pbufFwd = pBufInit;
             pBufInit->BufLru.pbufBak = pBufInit;

             /* set forward and backward lru pointers */
             DCADDF (pBufInit, BufFreeLru, BufFreeList);
             ++pBufInit;
             ++FreeBufs;
          }
          /* Clear CacheToAlloc so that init\iniproc1.asm does not try to
             display an error message to user. */
          CacheToAlloc = 0;
          /* if no FAT partitions and D is on diskcache statement */
          if ((Defaultcache) && (fatvolume == 0))  /* remove FAT cache */
          {
          rc = ReleaseFATCache();
          }
       }
    }
    return;
}
/***EP  ReleaseFATCache -Releases the FAT Cache memory
 *
 *      Releases  The FAT cache memory
 *
 *      ENTRY   None
 *
 *      EXIT
 *
 *
 *
 *
 */

int  ReleaseFATCache()
{
    int                 rc = 0;

    FATCache = 0;                /* set global flag no cache for FAT */

    if (cachebuffer1 != 0)  /* free cache if buffer is != 0 */
          {
          if (rc = VMFreeMem((ulong_t)cachebuffer1,HOBNULL,0))
             return(rc);
          }
    if (cachebuffer2 != 0)  /* free cache if buffer is != 0 */
          {
          if (rc = VMFreeMem((ulong_t)cachebuffer2,HOBNULL,0))
             return(rc);
          }
    if (cachebuffer3 != 0)  /* free cache if buffer is != 0 */
          {
          if (rc = VMFreeMem((ulong_t)cachebuffer3,HOBNULL,0))
             return(rc);
          }
    if (cachebuffer4 != 0)  /* free cache if buffer is != 0 */
          {
          if (rc = VMFreeMem((ulong_t)cachebuffer4,HOBNULL,0))
             return(rc);
          }
    return(0);
}
