/*static char *SCCSID = "@(#)fs_opnpf.c	6.2 92/01/31";*/

#define INCL_DOSERRORS
#include <os2def.h>
#include <bse.h>
#include <strat2.h>

#include "const.h"
#include "misc.h"
#include "chain.h"
#include "buf.h"
#include "dir.h"
#include "volume.h"
#include "frame.h"
#include "asyncio.h"
#include "storage.h"
#include "tables.h"
#include "pb_ifs.h"
#include "lw.h"
#include "fsdata.h"
#include "heap.h"
#include "pr_fsd.h"
#include "pr_HEAP.h"
#include "pr_MISC.h"

#include "pr_DEBUG.h"

/***	FS_OpenPageFile - Create/Open Paging File
 *
 *	FS_OpenPageFile creates (first call) or opens (subsequent calls) the
 *	specified page file.
 *
 *	Enough information is provided do call perform a normal create/open.
 *
 *	Since a page file has special requirements about contiguity of its
 *	allocation, FS_OpenPageFile must assure that any data sectors allocated
 *	are returned (first call only).  FS_AllocatePageSpace will be called to
 *	handle file allocation.
 *
 *	If the FSD cannot support FS_DoPageIO (usually due to an old disk driver
 *	which does not support the Strategy2 entry point) can return 0 for
 *	*pcMaxReq, which tells the kernel that it must emulate FS_DoPageIO.
 *
 *	The FSD can require either physical or virtual (16:16) addresses for
 *	subsequent calls to FS_DoPageIO.  This allows an FSD to emulate
 *	FS_DoPageIO without having to worry about dealing with physical
 *	addresses.
 *
 *	ENTRY	*pFlags	  = FirstOpen flag
 *		*pName	  = Name of page file
 *		psffsi	  = File System Independent portion of SFT
 *		psffsd	  = File System Dependent portion of SFT
 *		OpenMode  = For Open/Create (see fcn\open.c)
 *		OpenFlag  = For Open/Create (see fcn\open.c)
 *		Attr	  = For Open/Create (see fcn\open.c)
 *		Reserved  = 0
 *
 *	EXIT  Returns 0 if OK
 *		*pFlags	  = Virtual/Physical Address flags
 *		*pcMaxReq = Maximum number of requests per PageCommandList
 *			    (0 means that this FSD cannot accept the FS_DoPagIO
 *			     requests - usually due to an old disk driver that
 *			     not support the Strategy2 entry point)
 *		*psffsd	  = Filled in as necessary
 *
 *	      Returns non-zero error code if error
 ***/

int far pascal
FS_OPENPAGEFILE (PULONG		    pFlags,	/* FirstOpen, Phys/Virt-Addr */
		 PULONG		    pcMaxReq,	/* returned max req list len */
		 PCHAR		    pName,	/* Name of page file */
		 struct sffsi far * psffsi,	/* sft - fs independent */
		 struct sffsd far * psffsd,	/* sft - fs dependent */
		 USHORT		    OpenMode,	/* for open/create */
		 USHORT		    OpenFlag,	/* for open/create */
		 USHORT		    Attr,	/* for open/create */
		 ULONG		    Reserved)



{
    int usRet;
    FRAME frm;

    /**** - We are going to call FS_OPENCREATE and FS_NEWSIZE; they handle
     ****   their own frames.  So we don't set up a frame until we need it.
     ****/

#ifdef DEBUG
    if (*pFlags & PGIO_FIRSTOPEN) {
	dprintf (__FILE__": *pFlags = %x (PGIO_FIRSTOPEN)\n", *pFlags);
    } else {
	dprintf (__FILE__": *pFlags = %x (not PGIO_FIRSTOPEN)\n", *pFlags);
    }
#endif

    {
	BOOL fGenFlag = 0;
	USHORT RetAction;

	/* Open/Create page file */
	    usRet = FS_OPENCREATE (NULL, NULL,		    /* no CDS */
				   pName,
				   -1,			    /* ignore CDS */
				   psffsi, psffsd,
				   OpenMode, OpenFlag,
				   &RetAction, Attr,
				   NULL,		    /* no EAs */
				   &fGenFlag);

	if (usRet) {
	    return usRet;
	}
    }

    if (*pFlags & PGIO_FIRSTOPEN) {
	/* Since FS_OpenCreate may allocate 7 sectors, lets be sure to get rid
	 * of them, so space allocation will start out on page boundaries.
	 */
	usRet = FS_NEWSIZE (psffsi, psffsd,
			    0L,			    /* new size = 0 */
			    0);			    /* no IOFlags */

	if (usRet) {
	    return usRet;
	}
    }	/* if first-open */

    frm.usHardErr = NO_ERROR;
    frm.fRecheckAddr = TRUE;

    {
	PFHT pfht;
	PVOLTAB pvol;

	pfht = ((PPB_SFD)(psffsd->sfd_work))->pfht;
	pvol = pfht->poft->pVolume;

	/* Check to see if disk driver supports Strategy 2 */

	if (IsAsyncIOable (pvol->ulVolBits)) {

//test. force strat1
//  goto strat1;

	    /* DD has Strategy 2, our DoPageIO will work */

	    *pcMaxReq = (pvol->csgMax) ? pvol->csgMax : HPFS_MAXREQ;

	    if (*pcMaxReq > HPFS_MAXREQ) {
#ifdef DEBUG
		dprintf (__FILE__": *pcMaxReq  (%d) > HPFS_MAXREQ (%d)\n",
			 *pcMaxReq, HPFS_MAXREQ);
		Int3 ();
#endif
		*pcMaxReq = HPFS_MAXREQ;

	    }

	    *pFlags |= PGIO_PADDR;

	    /*
	     * We have to allocate an IOHandle for this SFT -
	     *
	     * Save it in *pfht.
	     * We reuse offseek in the fht for this purpose.  We never use
	     * offseek when doing pager I/O.
	     *
	     * We don't specify any flags to GetIOHand because FS_DoPageIO
	     * always calls ResetIOH before using this IOHandle.
	     */
	    pfht->offSeek = (ULONG)GetIOHand(pvol->ulVolBits,
					     (USHORT) *pcMaxReq,
					     ONESGLIST, &frm);
	} else {
//test
strat1:
	    /* DD doesn't have Strategy 2, kernel can emulate DoPageIO */
	    *pcMaxReq = 0;
	    *pFlags |= PGIO_VADDR;
	}
    }

    return NO_ERROR;

    /* to avoid compiler warning */
    (VOID)Reserved;
}   /* FS_OPENPAGEFILE */
