/*static char *SCCSID = "@(#)fs_mount.c 6.3 92/01/31";*/
#define _BTXT _BTXT
#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include <fsh.h>
#include "heap.h"
#include "const.h"
#include "chain.h"
#include "misc.h"
#include "buf.h"
#include "dir.h"
#include "storage.h"
#include "volume.h"
#include "tables.h"
#include "pb_ifs.h"
#include "pbmacros.h"
#include "lw.h"
#include "frame.h"
#include "fsdata.h"
#include "boot.h"
#include "shutdown.h"
#include "pr_fsd.h"
#include "pr_FSINI.h"
#include "pr_HEAP.h"
#include "pr_MISC.h"
#include "pr_DEBUG.h"

extern BOOL fCacheInit;                 /* Cache already init?  see init2.c */
extern BOOL fInit2Free;

/* put volume mounting functions in different code segment */


/*
 ***    FS_MOUNT - Mounts a Pinball file system.
 *
 *      Check to see that for this version, the operation requested is
 *      supported.
 *
 *      Calls MFS to mount the pinball file system.
 *
 *      ENTRY   fsOper = bits turned on indicating operation requested.
 *              pcpfsi = pointer to file system independent portion of VPB.
 *              pvpfsd = pointer to file system dependent portion of VPB.
 *              hVPB = volume handle
 *              pcBoot = pointer to sector 0 read from the media.
 *
 *      EXIT    Returns NO_ERROR iff mount successful
 *
 *      HISTORY
 *          27-Feb-1990 by JR (John Rogers, JohnRo@Microsoft)
 *              - PTR B788315: init swap lock area sooner.
 *          23-Feb-1990 by JR (John Rogers, JohnRo@Microsoft)
 *              - PTR B788262: fix FS_DoPageIO probs (e.g. nested swap).
 *          01-Nov-89 by JR (John Rogers, JohnRo@Microsoft)
 *              - PTR B786561: Handle failed mem realloc.
 *          19-Sep-89 by JR (John Rogers, JohnRo@Microsoft)
 *              - Avoid warnings from Microsoft C 5.2 (on slash-slash comments).
 *          22-Jun-1989 by JR (John Rogers, JohnRo@Microsoft)
 *              - PTR B784106: Allow DosRead() of force-mounted volume.
 *          26-May-1989 by JR (John Rogers, JohnRo@Microsoft)
 *              - DCR 259.2: added counting of write threads for shutdown.
 *              - DCR 259.2: changed names of macros in "frame.h".
 *              - Changed to combine exit logic at end of FS_MOUNT.
 */


INT far pascal
FS_MOUNT (USHORT            fsOper, /* operation requested */
          struct vpfsi far *pvpfsi, /* ptr to file sys indep part of VPB */
          struct vpfsd far *pvpfsd, /* ptr to file sys dependent part of VPB */
          SHANDLE           hVPB,   /* volume handle */
          PCHAR             pBoot)  /* pointer to sector 0 */
{
    ULONG csecMax;                      /* Sectors on volume (0 if unknown). */
    INT iRet;
    FRAME frm;
    SHUTDOWN_LOCAL_VARS;

    frm.usHardErr = NO_ERROR;
    frm.fRecheckAddr = TRUE;
    frm.fFlag = 0;               // Clear Frame flag  @132506

    if (!fInit) {
        HeapInit(&frm);
        fInit = TRUE;
    }

    INCR_WRITE_THREADS;                 /* Tell shutdown we're writing. */

#ifndef MINIFSD
    /*
     * Now that we've used the init code we can free the segment.
     */
    if (!fInit1Free) {
        FreeInit1 ();
    }

    if (!fCacheInit) {

        iRet = (INT)Init2(&frm);

        if (iRet != NO_ERROR) {
            goto Mntexit;
        }

        fCacheInit = TRUE;
    }

#endif

    /*
     * Compute number of sectors on volume, if possible.  (We might use the
     * value from the boot sector if the super block is corrupt.)
     */
    if (pBoot != NULL)
        csecMax = ((PEXTENDED_BOOT) pBoot) -> Boot_BPB.Ext_totalSectors;
    else
        csecMax = 0L;                   /* Unknown. */

    switch (fsOper) {

    case MOUNT_MOUNT:
        if (!PinballDisk (pBoot)) {
            /*
             * Pinball does not recognize the volume id--it must not
             * be a pinball file system!  Return appropriate error, for
             * now this is the only appropriate code available.
             */
            iRet = ERROR_NOT_SUPPORTED;
            break;
        }

        /* we recognize the volume id - fall through */

    case MOUNT_VOL_REMOVED:
    case MOUNT_RELEASE:
    case MOUNT_ACCEPT:

        LOCKSWAP(&swapBSWAP1);

        iRet = MFS (hVPB, fsOper, pvpfsi, csecMax, &frm);

        UNLOCKSWAP(&swapBSWAP1);

#ifndef MINIFSD
        /*
         * Now that MFS has used the cache init routines we can free
         * that segment.  Check the boolean so we only free this ONCE.
         */
        if (iRet == NO_ERROR) {

            if (!fInit2Free) {
                iRet = FreeInit2 ();
            }
        }
#endif

#ifdef DEBUG
        if (fCacheInit) {
            VBS ();
        }
#endif
        break;

    default:
        iRet = ERROR_NOT_SUPPORTED;
    }

    /* Clean-up and exit. */
Mntexit:
    DECR_WRITE_THREADS;         /* Tell shutdown we're done. */
    return (iRet);

    /* Get rid of -W3 warnings */
    pvpfsd;
}


#define PINBALL_ID              "HPFS    "
#define OLD_PINBALL_ID          "PINBALL "

/* #define TEMPORARILY */

#ifdef TEMPORARILY
char *pcTmpMsgText = "You need to reformat with the latest HPFS format\n";
#define TMP_MSG_TEXT_LEN        49
#endif

STATIC BOOL
PinballDisk (pcBoot)
PCHAR pcBoot;
{
    /* if the ID field doesn't match the correct one... */
    if (memcmp (((PEXTENDED_BOOT) pcBoot)->Boot_System_ID,
                PINBALL_ID,
                SYS_ID_LEN)) {

#ifdef TEMPORARILY
        /*
         * Well, it's not the correct up to date ID so check if
         * it is an old one.
         */
        if (memcmp (((PEXTENDED_BOOT) pcBoot)->Boot_System_ID,
                    OLD_PINBALL_ID,
                    SYS_ID_LEN)) {

                /* not the old one either */
                return (FALSE);
        }

        /* Yes, this is the old one. */
        FS_MAYBLOCK (
            FSH_CRITERROR (TMP_MSG_TEXT_LEN, pcTmpMsgText, 0, NULL, CE_ALLFAIL);
        );
#endif

        return (FALSE);
    }
    return (TRUE);
}
