/*DDK*************************************************************************/
/*                                                                           */
/* COPYRIGHT    Copyright (C) 1995 IBM Corporation                           */
/*                                                                           */
/*    The following IBM OS/2 WARP source code is provided to you solely for  */
/*    the purpose of assisting you in your development of OS/2 WARP device   */
/*    drivers. You may use this code in accordance with the IBM License      */
/*    Agreement provided in the IBM Device Driver Source Kit for OS/2. This  */
/*    Copyright statement may not be removed.                                */
/*                                                                           */
/*****************************************************************************/
/**************************************************************************
 *
 * SOURCE FILE NAME = VVUSER.C
 *
 * DESCRIPTIVE NAME = Virtual Video Device Driver User-event Processing
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's user-event handlers.
 *
 *
 * FUNCTIONS    VVCreate()              VDM creation notification
 *              VVCreateDone()          VDM creation done notification
 *              vvEditXGAInstance()     Edit XGA Instance
 *              vvEditXGAInstancePLE()  Edit XGA Instance PLE
 *              vvSVGAEditVideoTables() Called once to do SVGA-specific
 *                                      initialisation
 *              VVSetFgnd()             VDM foreground notification
 *              VVSetBgnd()             VDM background notification
 *              VVChangeCodePage()      VDM codepage change notification
 *              VVChangeTitle()         VDM title change notification
 *              VVDestroy()             VDM termination notification
 *              VVSetInt10Emulation     Set per-VDM INT 10h emulation flag
 *              VVSetRetraceEmulation   Set per-VDM retrace emulation flag
 *              VVSetUpdateFrequency    Set per-VDM graphics update frequency
 *              VVSetInt2F              Set per-VDM INT 2Fh flag
 *              VVSetOnDemandAlloc      Set per-VDM on-demand allocation flag
 *              VVFgndContext()         Finish foreground switch in VDM's context
 *              VVBgndContext()         Finish background switch in VDM's context
 *              vvFreezeVDM()           Worker to freeze VDM/notify Shield
 *              vvThawVDM()             Worker to thaw VDM/notify Shield
 *              vvInt2FNotify()         Worker to issue INT 2Fh to VDM
 *              vvInt2FReturn()         Return hook for our INT 2Fh calls
 *              VDHRegisterInt2FProc    INT 2F registration routine
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


#include <mvdm.h>
#include <vvd.h>
#include "vvdp.h"
#ifdef  GALE                                                            //J-TS00V
#include <propname.h>                                                   //J-TS00V
#include <vfntv.h>                                                      //J-TS00V
#include <vbios.h>                                                      //J-TS00V
#include "vvgale.h"                                                     //J-TS00V
#endif  //GALE                                                          //J-TS00V

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif
extern ULONG flVVD;
/*extern BOOL  flBigSel = FALSE;                            73541           */

#ifdef   VGA                                     /*                         */
extern FLAGS flNotifyType;                       /*                         */
extern PFNINT2FP pfnInt2FProc;                   /*                         */
#endif                                           /*                         */
#pragma  BEGIN_SWAP_DATA
extern HVDM hvdmFocus;
extern HVDM hvdmUpdate;
extern PSZ pszVVDName;
extern PBVDM pvdmROMFont;
extern ULONG nbROMFontEntry;
extern ULONG npgPhysVRAM;
extern HVDD hvddMouse;
extern VMREG vmreg;
extern VMFUNC vmfunc;
#ifdef  GALE                                                            //J-TS00V
extern HVDD    hvddVfontV;                                              //J-TS00V
extern BOOL    (PRIVENTRY *vfvfunc[])();                                //J-TS00V
#endif  //GALE                                                          //J-TS00V
extern HLE ahleFgnd[];
extern HLE ahleBgnd[];
extern PLE apleAll[];                                           /*            */
extern PLE apleNoTrap[];                                        /*            */
extern LSENTRY lseHeadActive;
extern ULONG nWindowedEvents;
extern HMXSEM hmxWindowedEvent;
extern PBVDM pvdmPhysVRAM;
extern ULONG nWindowedVDMs;
extern ULONG nPMWindowedVDMs;
extern ULONG nMinWindowedVDMs;

#ifdef   VGA
extern BYTE aregSEQInit[];
extern BYTE aregGDCInit[];                       /*                         */
extern BYTE aregCRTInit[];                       /*                         */
extern ULONG flXGAPresent;                       /*                         */
#endif

#ifdef   SVGA
extern RLE arleMemory[];                                        /*            */
extern OEMSVGAINFO sSVGA;                                       /*            */
extern BYTE aregATIInit[ATI_TOTAL_INITREGS];
extern ULONG    ulWD_MASK_GDCLOCK;                              /*            */
extern ULONG    ulWD_MASK_CRTLOCK;                              /*            */
extern ULONG    ulWD_MASK_SEQLOCK;                              /*            */
extern ULONG    ulNumLockCmds;                                  /*            */
extern ULONG    ulNumUnLockCmds;                                /*            */
extern USHORT   ausLockReg[];                                   /*            */
extern USHORT   ausLockCmd[];                                   /*            */
extern PFNSVGAGETBANK  apfnSVGAGetBank[];                       /*            */
extern BOOL     flBgndExecSupported;                            /*            */
#endif

#ifdef   PROPERTIES
#ifdef  GALE                                                            //J-TS00V
extern SZ szPropDBCSInputEnv;                                           //J-TS00V
#endif  //GALE                                                          //J-TS00V
extern SZ szPropInt10Emulate;
extern SZ szPropRtrcEmulate;
extern SZ szPropModeRestrict;
extern SZ szPropNoRestrict;
extern SZ szPropCGARestrict;
extern SZ szPropIOTrap;                                         /*            */
extern SZ szDOSBgndExec;                                        /*            */

   #ifndef  CGA
extern SZ szPropMONORestrict;
   #endif
extern SZ szPropUpdateWindow;

extern SZ szPropInt2F;
extern SZ szPropOnDemandAlloc;
extern SZ szVMBoot;
#endif

#ifdef   SVGA
extern ULONG ulSVGAChipType;
extern ULONG ulSVGAAdapterType;
extern ULONG ulSVGAVRAMSize;                    /*                          */
extern BOOL fPMIProcessed,fPMILoaded,fSeqFixups;
extern ULONG ulXGAInstance;                     /*                          */
extern PFNSVGASETBANK apfnSVGASetBank[];
#endif

#ifdef  GALE                                                            //J-TS00V
typedef struct CodePages_s {                                            //J-TS00V
ULONG    cp_cp2;                                                        //J-TS00V
ULONG    cp_cp1;                                                        //J-TS00V
} CodePages;                                                            //J-TS00V
                                                                        //J-TS00V
typedef CodePages   *PCodePages;                                        //J-TS00V
                                                                        //J-TS00V
CodePages CodePagesTable[] = {                                          //J-TS00V
      {942,932},     /* Japan country 81  */                            //J-TS00V
      {944,934},     /* Karea         82  */                            //J-TS00V
      {948,938},     /* Taiwan        88  */                            //J-TS00V
      {946,936},     /* PRC           86  */                            //J-TS00V
      {0}                                                               //J-TS00V
};                                                                      //J-TS00V
#endif  //GALE                                                          //J-TS00V
#ifdef  XVIO                                                            //J-TS00V
extern HVDD       hvddVXVIO;                                            //J-TS00V
extern VXREGISTER XVIOEntry;                                            //J-TS00V
extern VXENTRYSV  VVDEntry;                                             //J-TS00V
#endif  //XVIO                                                          //J-TS00V

#pragma  END_SWAP_DATA

#ifdef   EGAVGA
   #pragma  BEGIN_GLOBAL_DATA
extern HVDM hvdmController;
   #pragma  END_GLOBAL_DATA
#endif
#pragma  BEGIN_SWAP_CODE

/***************************************************************************
 *
 * FUNCTION NAME = VVCreate()
 *
 * DESCRIPTION   = VDM creation notification
 *
 *                 This registered subroutine is called each time a new VDM
 *                 is created (see VDHInstallUserHook for complete
 *                 semantics).
 *
 *                 Virtual memory buffer(s) are fully allocated at this time
 *                 to insure the system *could* bring the VDM foreground
 *                 later.  If the VDM is being started in the foreground,
 *                 then when SetFgnd grows the buffers, effectively nothing
 *                 happens, since they were already grown here; if the VDM is
 *                 being started in the background, then when SetBgnd shrinks
 *                 the buffers, they will be shrunken normally.  "Spiking"
 *                 the system's memory overcommit in this way should help
 *                 eliminate the chance of an interactive DOS application,
 *                 started in the background, beginning some critical
 *                 operation which must be brought foreground and yet can't.
 *                 Forcing the user to kill off such a VDM is highly
 *                 undesirable.
 *
 *
 *
 *
 * INPUT         = hvdm -> new VDM
 *
 * OUTPUT        = SUCCESS
 *                     TRUE (new VDM accepted)
 *                 FAILURE
 *                     FALSE (eg, not enough memory)
 *                     It is assumed that
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 *  PSEUDO-CODE
 *                 determine ownership
 *                 allocate maximum background storage for VDM
 *                 if error
 *                   fail the creation
 *                 define video software interrupt hook
 *                 establish communication with virtual mouse driver
 *
 **************************************************************************/

BOOL EXPENTRY VVCreate(HVDM hvdm)
{
  register INT i;
  PSZ pszTmp;
  PBVDM pvdmEBIOS;
  ULONG nbRMSize,nbTotalSize;
  INT iVirt, tmp;   //V2.0JWK61
  HHOOK hhook;      //V2.0JWK61

#ifdef   SVGA
  USHORT svga;
  PHLE phle;
  BYTE bIndex;                                                  /*            */
#endif

#ifdef  GALE                                                            //J-TS00V
  PBYTE PropStr;                                                        //J-TS00V
#endif  //GALE                                                          //J-TS00V

#ifdef   SVGA

  if (!fPMIProcessed)
  {

    /*
    ** Determine the SVGA chipset and adapter
    */

    fPMIProcessed = fPMILoaded = FALSE;
    if (vvIdentifySVGA(&sSVGA))                /*              */
    {                                          /* 1 is success */
        ulSVGAChipType = (ULONG) sSVGA.ChipType;
        ulSVGAAdapterType = (ULONG) sSVGA.AdapterType;
        ulSVGAVRAMSize = sSVGA.Memory;
        switch (ulSVGAAdapterType) {
           case TSENG_ADAPTER:                       /*            */
           case WESTERNDIG_ADAPTER:                  /*            */
           case CIRRUS_ADAPTER:                      /*            */
           case S3_ADAPTER:                          /*            */
                fSeqFixups = FALSE;
                break;
           default:
                fSeqFixups = TRUE;
        } /* endswitch */
        fPMILoaded = vvProcessPMIFile(SVGA_PMIFILENAME);
        fPMIProcessed = TRUE;
    }
                                                /*             end */

    if (!fPMILoaded)
    {                                            /* NOP any SVGA
                                                    functionality           */
      ulSVGAChipType = 0;
      ulSVGAAdapterType = 0;
    }
    else
    {
      vvSVGAEditVideoTables(ulSVGAAdapterType, ulSVGAChipType); /*            */
    }
  }
#endif

  /*
  ** NOTES ON SEMAPHORE HIERARCHY
  ** (maintained in vvinit.c and vvuser.c)
  **
  ** The Video VDD's semaphore hierarchy is as follows:
  **
  **  1. hmxWindowedState
  **  2. hmxVideoState
  **  3. hvdmController
  **  4. hmxPhysPageEvent
  **  5. hmxWindowedEvent
  **  6. hmxPhysLatch
  **
  ** The per-VDM semaphores are first, because we generally enter the VDD
  ** in (or on behalf of) a VDM's context.  hvdmController is next because
  ** of the constraints of our interface with the PM display driver (see
  ** vvGetPhysBytes and vvFreePhysBytes for more details).  From that point
  ** on, the semaphores are basically in order of high-level to low-level
  ** operation.
  **
  ** Note that driver entry points can enter the hierarchy at any point,
  ** but must take care to not call routines that require semaphores at some
  ** higher point.  I need to eventually build some assertion checking into
  ** the RequestMutexSem macro, but because some are per-vdm and some are
  ** not conventional (ie, hvdmController), it'll take some time....
  */

  /*
  ** Allocate all per-VDM semaphores
  */

  if (!CreateMutexSem(&pVDMData(hvdm)->hmxWindowedState))
    return  FALSE;


  if (!CreateMutexSem(&pVDMData(hvdm)->hmxVideoState))
    return  FALSE;


  if (!CreateEventSem(&pVDMData(hvdm)->hevFreezeThaw))
    return  FALSE;


  if (!CreateEventSem(&pVDMData(hvdm)->hevShieldSynced))
    return  FALSE;

#ifdef SVGA
  if (!CreateEventSem(&pVDMData(hvdm)->hevInt2FDelaySwitch))
    return  FALSE;
  /* 8514IO semaphore should never be in use by non-8514 SVGA devices */
  if (ulSVGAAdapterType == S3_ADAPTER)                  /*            */
  {
    if (!CreateEventSem(&pVDMData(hvdm)->hev8514WakeUp))
      return  FALSE;
    if (!CreateEventSem(&pVDMData(hvdm)->hev8514Busy))
      return  FALSE;
  }
  else
  {
    pVDMData(hvdm)->hev8514WakeUp = (HEVSEM) NULL;
    pVDMData(hvdm)->hev8514Busy = (HEVSEM) NULL;
  }
#endif
  /*
  ** Allocate context hook handles
  */

  if ((VDMData.hhookFgndContext = VDHAllocHook(VDH_CONTEXT_HOOK,
                                               (PFNARM)VVFgndContext,
                                               0)) == NULL)
  {
    return  FALSE;
  }


  if ((VDMData.hhookBgndContext = VDHAllocHook(VDH_CONTEXT_HOOK,
                                               (PFNARM)VVBgndContext,
                                               0)) == NULL)
  {
    return  FALSE;
  }


  if ((VDMData.hhookInitContext = VDHAllocHook(VDH_CONTEXT_HOOK,
                                               (PFNARM)VVInitContext,
                                               sizeof(BOOL))) == NULL)
  {
    return  FALSE;
  }


  if ((VDMData.hhookUpdatePtrContext = VDHAllocHook(VDH_CONTEXT_HOOK,
                                                    (PFNARM)VVUpdatePtrContext,
                                                    sizeof(ULONG))) == NULL)
  {
    return  FALSE;
  }

#ifdef   EGAVGA

  if ((VDMData.hhookUpdateContext = VDHAllocHook(VDH_CONTEXT_HOOK,
                                                 (PFNARM)VVUpdateContext,
                                                 0)) == NULL)
  {
    return  FALSE;
  }


  if ((VDMData.hhookUpdatePhysContext = VDHAllocHook(VDH_CONTEXT_HOOK,
                                                     (PFNARM)
                                                        VVUpdatePhysContext,
                                                     0)) == NULL)
  {
    return  FALSE;
  }

  if (ALLOCHOOK((PFNARM)VVUnmapPhysContext, 1,VDMData.hhookUnMapPhysContext , tmp)) {    //V2.0JWK61
                                                                                         //V2.0JWK61
     HOOKDATA(VDMData.hhookUnMapPhysContext, 0) = 0;                                     //V2.0JWK61
  }                                                                                      //V2.0JWK61
  else                                                                                   //V2.0JWK61
  {                                                                                      //V2.0JWK61
      return FALSE;                                                                      //V2.0JWK61
  }                                                                                      //V2.0JWK61
#endif    //V2.0JWK61 need only if egavga

   /*
   ** Allocate return hook handles
   */

  if ((VDMData.hhookInt10SetModeReturn = VDHAllocHook(VDH_RETURN_HOOK,
                                                      (PFNARM)
                                                      VVInt10SetModeReturn,
                                                      0)) == NULL)
  {
    return  FALSE;
  }


  if ((VDMData.hhookInt10Return = VDHAllocHook(VDH_RETURN_HOOK,
                                               (PFNARM)VVInt10Return,
                                               sizeof(VVINT10S))) == NULL)
  {                                              /*                         */
    return  FALSE;
  }

#ifdef  VTEXT                                                           //J-TS00V
  if ((VDMData.GaleData.hhookVtextReturn =                              //J-TS00V
        VDHAllocHook(VDH_RETURN_HOOK,                                   //J-TS00V
                     (PFNARM)VVCheckVtextReturn, 0)) == NULL) {         //J-TS00V
    return FALSE;                                                       //J-TS00V
  }                                                                     //J-TS00V
                                                                        //J-TS00V
  if ((VDMData.GaleData.hhookVtextHook =                                //J-TS00V
        VDHAllocHook(VDH_BP_HOOK,                                       //J-TS00V
                     (PFNARM)VVInt10VtextHook, 0)) == NULL) {           //J-TS00V
    return FALSE;                                                       //J-TS00V
  }                                                                     //J-TS00V
                                                                        //J-TS00V
  if ((VDMData.GaleData.hhookVtextPreHook =                             //J-TS00V
        VDHAllocHook(VDH_BP_HOOK,                                       //J-TS00V
                     (PFNARM)VVInt10VtextPreHook, 0)) == NULL) {        //J-TS00V
    return FALSE;                                                       //J-TS00V
  }                                                                     //J-TS00V
                                                                        //J-TS00V
  if ((VDMData.GaleData.hhookVtextRedrawReturn =                        //J-TS00V
        VDHAllocHook(VDH_RETURN_HOOK,                                   //J-TS00V
                     (PFNARM)VVVtextRedrawReturn, 0)) == NULL) {        //J-TS00V
    return FALSE;                                                       //J-TS00V
  }                                                                     //J-TS00V
                                                                        //J-TS00V
  if ((VDMData.GaleData.hhookVextPtrContext =                           //J-TS00V
        VDHAllocHook(VDH_CONTEXT_HOOK,                                  //J-TS00V
                     (PFNARM)VVVtextUpdatePtrContext, 0)) == NULL) {    //J-TS00V
    return  FALSE;                                                      //J-TS00V
  }                                                                     //J-TS00V
                                                                        //J-TS00V
  if ((VDMData.GaleData.hhookVextPtrReturn =                            //J-TS00V
        VDHAllocHook(VDH_RETURN_HOOK,                                   //J-TS00V
                     (PFNARM)VVVtextPtrReturn, 0)) == NULL) {           //J-TS00V
    return FALSE;                                                       //J-TS00V
  }                                                                     //J-TS00V
#endif  //VTEXT                                                         //J-TS00V


  if ((VDMData.hhookInt2FReturn = VDHAllocHook(VDH_RETURN_HOOK,
                                               (PFNARM)VVInt2FReturn,
                                               0)) == NULL)
  {
    return  FALSE;
  }

  VDMData.pInt10ReturnData = VDHQueryHookData(VDMData.hhookInt10Return);
  ((PVVINT10S)(VDMData.pInt10ReturnData))->func_type = 0;/*                 */

  /*
  ** Stash the handle and SGID away immediately
  */

  VDMData.hvdmVideo = hvdm;
  VDMData.sgIDVideo = VDHQuerySysValue(hvdm,
                                       VDHLSV_SESSIONID);

   /*
   ** Initial pointer state is "frozen" **
   */

  VDMData.PtrData.fPtrFrozenVideo++;

  /*
  ** Primary display is by default the active display
  */

#ifdef   MONO
  VDMData.flVDMXVideo |= (VDMX_DEVOWNER|VDMX_DSPOWNER|/*                    */
     VDMX_SAVERESTORE);                          /*                         */

#else
  VDMData.flVDMXVideo |= (VDMX_ACTIVE|VDMX_DEVOWNER|/*                      */
     VDMX_DSPOWNER|VDMX_SAVERESTORE);            /*                         */
#endif

  /*
  ** Initialize map target structures
  */

  for (i = 0; i < npgPhysVRAM; i++)
  {
    VDMData.ulMapCur[i] = VDMData.avdhmt[i].vdhmt_laddr | VDHMT_INVALID; /*            */
    VDMData.avdhmt[i].vdhmt_laddr = (ULONG)pvdmPhysVRAM+i *PAGESIZE;
    VDMData.avdhmt[i].vdhmt_cpg = 1;
    VDMData.avdhmt[i].vdhmt_hmap = 0;
  }
#ifdef PROPERTIES

  /*
  ** Obtain all the correct property settings
  */

  if (VDHQueryProperty(szPropInt10Emulate))
    VDMData.flVDMXVideo |= VDMX_INT10EMULATE;

  if (VDHQueryProperty(szPropRtrcEmulate))
    VDMData.flVDMXVideo |= VDMX_RTRCEMULATE;

  if (!VDHQueryProperty(szPropIOTrap))                          /*            */
    VDMData.flVDMXVideo |= VDMX_NOIOTRAPPING;                   /*            */
                                                                /*            */
#ifdef   SVGA
  VDMData.flBgndExecEnabled = flBgndExecSupported &&            /*            */
                              (BOOL)VDHQueryProperty(szDOSBgndExec);
#endif

  if (VDHQueryProperty(szPropInt2F))
    VDMData.flVDMXVideo |= VDMX_INT2F;

  if (VDHQueryProperty(szPropOnDemandAlloc))
    VDMData.flVDMXVideo |= VDMX_ONDEMAND;

  if (pszTmp = (PSZ)VDHQueryProperty(szVMBoot))

    if (*pszTmp)
      VDMData.flVDMXVideo |= VDMX_V86MACHINE;

  if (pszTmp)
  {                                              /* ssloop                  */
    VDHFreeMem(pszTmp);                          /* ssloop                  */
    pszTmp = NULL;                               /* ssloop                  */
  }                                              /* ssloop                  */
  VDMData.nPeriodicLimit = (VDHQueryProperty(szPropUpdateWindow)*100)/
     TIMER_CHECK;
#endif

#ifdef  GALE                                                            //J-TS00V
  PropStr = (PBYTE)VDHQueryProperty(szPropDBCSInputEnv);                //J-TS00V
  if (STRCOMPARE(PropStr, SINGLE_INPUT_METHOD, FALSE) == 0) {           //J-TS00V
    VDMData.GaleData.GaleDBCSInpEnv = DBCS_INPUT_SINGLE;                //J-TS00V
  } else if (STRCOMPARE(PropStr, DUAL_INPUT_METHODS, FALSE) == 0) {     //J-TS00V
    VDMData.GaleData.GaleDBCSInpEnv = DBCS_INPUT_DUAL;                  //J-TS00V
  } else {      // DOS_KKC_MODE                                         //J-TS00V
    VDMData.GaleData.GaleDBCSInpEnv = DBCS_INPUT_DOS_KKC;               //J-TS00V
  }                                                                     //J-TS00V
  VDMData.GaleData.flGaleFlags = 0;                                     //J-TS0331
#ifdef  VTEXT                                                           //J-TS00V
  VDMData.GaleData.flVtext    = 0;                                      //J-TS00V
  VDMData.GaleData.pVtextLVB  = NULL;                                   //J-TS00V
  VDMData.GaleData.pVtextPVB  = NULL;                                   //J-TS00V
#endif  //VTEXT                                                         //J-TS00V
#endif  //GALE                                                          //J-TS00V
#ifdef  XVIO                                                            //J-TS00V
  if (hvddVXVIO == NULL) {                                              //J-TS00V
    hvddVXVIO = VDHOpenVDD(VXVIO_NAME);                                 //J-TS00V
    if (hvddVXVIO != NULL) {                                            //J-TS00V
      VDHRequestVDD(hvddVXVIO, hvdm, VXDEVREQ_REGISTERVVD,              //J-TS00V
                    &VVDEntry, &XVIOEntry);                             //J-TS00V
    }                                                                   //J-TS00V
  }                                                                     //J-TS00V
  vxSetVVDType(hvdm, XVIOEntry.vxr_VVDID);                              //J-TS00V
#endif  //XVIO                                                          //J-TS00V

  /*
  ** Allocate maximum background storage for VDM
  */

  if (!(VDMData.flVDMXVideo&VDMX_ONDEMAND)
    && !vvGrowBuffer(hvdm, ALL_PLANES, GROW_MAXIMUM, BANK0))  /*           */
    return  FALSE;

  /*
  ** Hook all page faults
  */

  if (!vvSetFaultHooks(TRUE,
                       FALSE))
    return  FALSE;

  /*
  ** Hook all I/O ports
  */

  if (!vvSetIOHooks(ahleBgnd,
                    TRUE,
                    FALSE))
    return  FALSE;

#ifdef SVGA
  if (ulSVGAAdapterType == S3_ADAPTER)          /*            */
  {
    /*
    ** Claim the IOOWNED bit
    */

    v8514LockIO(hvdm);

    /*
    ** Install all I/O handlers. This will enable IO trapping for all
    ** ports but pixel transfer. If there is no IOTRAPPING in foreground,
    ** the trapping will be disabled on the first trapped port access.
    */

    v8514InstallIOHooks();
  }
#endif
  /*
  ** Hook video software interrupt
  */

  if (!VDHInstallIntHook(CURRENT_VDM,
                         BIOSINT_VIDEO,
                         VVInt10Hook,
                         VDH_ASM_HOOK))
    return  FALSE;

#ifdef  GALE                                                            //J-TS00V
    /*** Hook Gale Miscellanous software interrupt ***/                 //J-TS00V
    if ((BIOSMODE == DOSV_MODE) &&                                      //J-TS00V
        !VDHInstallIntHook(CURRENT_VDM,                                 //J-TS00V
                           BIOSINT_OSHOOK,                              //J-TS00V
                           VVInt15Hook, VDH_ASM_HOOK))                  //J-TS00V
        return FALSE;                                                   //J-TS00V
#endif  //GALE                                                          //J-TS00V

  VDMData.flVDMVideo |= VDM_BGNDREADY;

#ifdef   PROPERTIES

  /*
  ** Get the current RMSIZE, and convert to bytes
  */

  pvdmEBIOS = NULL;
  nbTotalSize = nbRMSize = BYTESFROMKB(VDHQuerySysValue(CURRENT_VDM,
                                                        VDHLSV_RMSIZE));

#ifdef  GALE                                                            //J-TS00V
  if (((ULONG)VDMBase.rb_awLPT[3] << 4) == nbRMSize) {                  //J-TS00V
    pvdmEBIOS = (PBVDM)((ULONG)VDMBase.rb_awLPT[3] << 4);               //J-TS00V
    nbTotalSize += *(UCHAR *)pvdmEBIOS * 0x400;                         //J-TS00V
  }                                                                     //J-TS00V
#else   //GALE                                                          //J-TS00V
  if (VDHQuerySysValue(CURRENT_VDM,
                       VDHGSV_MACHINETYPE) == MACHINE_TYPE_PS2)
  {
    pvdmEBIOS = (PBVDM)nbRMSize;
  }

  /*
  ** RMSize is returned as (A0000 - EBIOSDATA_LEN) for both MCA and
  ** ISA. Yet ISA doesn't have EBIOS area!  This fixes the "MODE RESTRICTION"
  ** lack of extra memory, but it would seem that this next line should
  ** be placed back in the PS2 conditional, QuerySysValue should return
  ** A0000 for ISA RM_SIZE.                                       
  */

  /*
  **            - Only add the 1K memory adjustment if the RMSize equals
  ** 639K.  OEM machines often return 640K and do need to be set to 641K.
  */

  if (nbTotalSize == EGAVGAMEM_START-EBIOSDATA_LEN)       /*            */
  {
    nbTotalSize += EBIOSDATA_LEN;                         /*            */
  }
#endif  //GALE                                                          //J-TS00V
#ifdef  GALE                                                            //J-TS00V
  if  (BIOSMODE == DOSV_MODE)                                           //J-TS00V
    VDMData.flVDMGale = TRUE;                                           //J-TS00V
                                                                        //J-TS00V
  if (VDMData.flVDMGale &&                                              //J-TS00V
    (VDMBase.rb_bVMode == 0x07))            // if MONO display          //J-TS00V
    VDMBase.rb_bVMode = 0x03;               // change to color          //J-TS00V
                                                                        //J-TS00V
  if (VDMData.flVDMGale) {                                              //J-TS00V
    PBYTE p;                                                            //J-TS00V
                                   //J-TS00V
                                   //J-TS00V
    if (!(VDMData.GaleData.GaleLVB                                      //J-TS00V
                    = VDHAllocDosMem(GALE_LVB_SIZE + 31 + 4)))          //J-TS00V
      return FALSE;                                                     //J-TS00V
    VDMData.GaleData.GaleLVB  =         /* LVB must have 0 offset */    //J-TS00V
            (PBYTE)(((ULONG)VDMData.GaleData.GaleLVB  + 31)             //J-TS00V
                            & 0xfffffff0L);                             //J-TS00V
                                /* 1 cell area just after LVB */        //J-TS00V
                                /* is reserved to avoid DBCS  */        //J-TS00V
                                /* write over run error check */        //J-TS00V
                                                                        //J-TS00V
    if (!(VDMData.GaleData.GaleSBCS                                     //J-TS00V
                    = VDHAllocDosMem(GALE_SBCS_FONT_SIZE + 15)))        //J-TS00V
      return FALSE;                                                     //J-TS00V
    VDMData.GaleData.GaleSBCS =         /* Font must have 0 offset */   //J-TS00V
            (PBYTE)(((ULONG)VDMData.GaleData.GaleSBCS + 15)             //J-TS00V
                            & 0xfffffff0L);                             //J-TS00V
                                                                        //J-TS00V
#ifdef  XVIO                                                            //J-TS00V
    if (!(VDMData.XVIOData.GaleXVIOLVB =        /* alloc XVIO LVB */    //J-TS00V
                (PBYTE)VDHAllocMem(GALE_LVB_SIZE, VDHAM_SWAPPABLE)))    //J-TS00V
      return FALSE;                                                     //J-TS00V
#endif  //XVIO                                                          //J-TS00V
                                                                        //J-TS00V
    if (!( p = VDHAllocDosMem(1)))                                      //J-TS00V
      return FALSE;                                                     //J-TS00V
    *p = 0xcf;                  /* iret */                              //J-TS00V
    VDMBase.rb_avpIVT[0x7d] = VPFROMP(p);                               //J-TS00V
  }                                                                     //J-TS00V
#endif  //GALE                                                          //J-TS00V

  /*
  ** If VDM size at max, then CGA/MONO restriction makes sense
  */

  if (nbTotalSize >= EGAVGAMEM_START)                   /*            */
  {
#ifdef  GALE                                                            //J-TS00V
    if (!VDMData.flVDMGale) {                                           //J-TS00V
#endif  //GALE                                                          //J-TS00V

    if (pszTmp = (PSZ)VDHQueryProperty(szPropModeRestrict))
    {

   #ifndef  CGA

      if (!strcmp(pszTmp+1,
                  szPropMONORestrict+1))
      {
        VDMData.flVDMXVideo |= VDMX_MONORESTRICT;
        VDMData.npgBonusBuffer = PAGESFROMBYTES(MONOMEM_START-EGAVGAMEM_START);
      }

      else
   #endif

        if (!strcmp(pszTmp,
                    szPropCGARestrict))
        {
          VDMData.flVDMXVideo |= VDMX_CGARESTRICT;
          VDMData.npgBonusBuffer = PAGESFROMBYTES(CGAMEM_START-EGAVGAMEM_START);

   #ifdef   VGA
          VDMBase.rb_bVMode = BIOSVMODE_CO80;
          VDMBase.rb_fsEquip &= ~BIOSEQUIP_VIDEOMASK;
          VDMBase.rb_fsEquip |= BIOSEQUIP_COLOR80VIDEO;
   #endif
        }
      VDHFreeMem(pszTmp);                        /* ssloop                  */
    }
#ifdef  GALE                                                            //J-TS00V
    }                                                                   //J-TS00V
#endif  //GALE                                                          //J-TS00V

    /*
    ** If CGA/MONO restriction was specified...
    */

    if (VDMData.npgBonusBuffer)
    {

      /*
      ** Allocate memory to fill in the reserved video region
      */

      VDMData.pBonusBuffer = VDHAllocPages(NULL,
                                           VDMData.npgBonusBuffer,
                                           VDHAP_SWAPPABLE);

      if (!VDMData.pBonusBuffer)
        return  FALSE;

      nbRMSize += VDMData.npgBonusBuffer *PAGESIZE;

      /*
      ** Copy EBIOS data from the page VBIOS allocated to the last
      ** page in our buffer
      */


      if (pvdmEBIOS)
      {
#ifdef  GALE                                                            //J-TS00V
        VDHCopyMem((PVOID)(pvdmEBIOS),                                  //J-TS00V
                   (PVOID)(VDMData.pBonusBuffer +                       //J-TS00V
                           VDMData.npgBonusBuffer*PAGESIZE -            //J-TS00V
                           *(UCHAR *)pvdmEBIOS * 0x400),                //J-TS00V
                   *(UCHAR *)pvdmEBIOS * 0x400);                        //J-TS00V
#else   //GALE                                                          //J-TS00V
        VDHCopyMem((PVOID)(pvdmEBIOS),
                   (PVOID)(VDMData.pBonusBuffer+VDMData.npgBonusBuffer
                      *PAGESIZE-EBIOSDATA_LEN),
                   EBIOSDATA_LEN);
#endif  //GALE                                                          //J-TS00V

        /*
        ** Fix up the ROM BIOS pointer to new EBIOS data area
        */

        VDMBase.rb_awLPT[3] = HISEG(nbRMSize);
      }

      /*
      ** Allocate memory for a stack we can switch to on SetMode
      */

      if (VDMData.flVDMXVideo&VDMX_V86MACHINE)
      {
        VDMData.pvdmAltStack = (PBVDM)nbRMSize;
        nbRMSize -= KBFROMBYTES(MAX_ALTSTACK)*KSIZE;
      }

      else
      {
        VDMData.pvdmAltStack = VDHAllocDosMem(MAX_ALTSTACK);

        if (!VDMData.pvdmAltStack)
          return  FALSE;

        VDMData.pvdmAltStack += MAX_ALTSTACK;
      }

      /*
      ** Update all the memory size fields
      */

      VDMBase.rb_wMemSize = (USHORT)KBFROMBYTES(nbRMSize);
      VDHPutSysValue(VDHLSV_RMSIZE,
                     VDMBase.rb_wMemSize);

      /*
      ** Lastly, because our fault hooks will not be installed
      ** in time to catch any kernel faults, we must map the memory.
      ** Remember: INVALID means invalid video page but VALID DOS page.
      */

      for (i = 0; i < VDMData.npgBonusBuffer; i++)
        vvMapPage((PBVDM)(EGAVGAMEM_START+i *PAGESIZE),
                  NULL,
                  ALL_PLANES,
                  BANK0,                                        /*            */
                  VDHMT_INVALID);
    }
  }
#endif                                           /* PROPERTIES              */

  /*
  ** Add this VDM's list-entry to the active VDM list
  */

RequestMutexSem(hmxWindowedEvent);
  ADDENTRY(hvdm,
           Active);
  ReleaseMutexSem(hmxWindowedEvent);

  /*
  ** Provide some fake instance data until the VDM's mode is set
  */

#ifdef   MONO
  VDMData.regMode = BIOSVMODE_MONO80;
#endif

#ifdef   CGA
  VDMData.regMode = VDMBase.rb_bVModeByte;
#endif

  /*
  ** Preset the Compaq mode control register shadow to allow correct output
  ** when coming full-screen from an initial windowed or iconized state.
   */

#ifdef   EGA                                     /*                         */
  VDMData.regCompaqCtrl = 1;                     /* Compaq Control Mode register*/
#endif                                           /*                         */

#ifdef   EGAVGA

  if (!(VDMBase.rb_bVInfo&BIOSVINFO_EGAMONO))
    VDMData.regMiscOut |= MISCOUT_COLRPORTS;     /* FLAG: - not good enough */
  VDMData.aregSEQData[REG_SEQRESET] = SEQRESET_ASYNC|SEQRESET_SYNC;
  VDMData.stateATC = ATC_INDEX;                  /* Init ATC to INDEX state
                                                                            */
#endif

#ifdef   VGA

  for (i = 0; i < MAX_SEQREGS; i++)
    VDMData.aregSEQData[i] = aregSEQInit[i];

  for (i = 0; i < MAX_GDCREGS; i++)              /*                         */
    VDMData.aregGDCData[i] = aregGDCInit[i];     /*                         */

  for (i = 0; i < MAX_CRTREGS; i++)              /*                         */
    VDMData.aregCRTData[i] = aregCRTInit[i];     /*                         */
#endif

#ifdef   SVGA
                                                        /*            start */
  VDMData.flVDMVideo |= VDM_FGND;                       /* force this for locking */

  /*
  ** If VDM is started in the bgnd in a way that VRAMISTOAST flag is
  ** reset before the first foreground for the VDM happens, the
  ** desktop will not be repainted although we are not capable of
  ** restoring its VRAM state. To circumvent this, on our first
  ** foreground, we make sure that VRAM is toasted. Hence, this flag
  ** needs to be set on VDM creation.
  */
  VDMData.flVDMX2Video |= VDMX2_FIRSTFGND;              /*            */
  vvUnLockSVGARegisters();

#ifdef   V21YEE05
/* This code should not be executed since the values are obtained at
   VDDINIT time and are already initialized earlier in this routine   */

  bIndex = INB(PORT_SEQINDX);
  for (i = 0; i < MAX_SEQREGS; i++) {
    OUTB(PORT_SEQINDX, i);
    if (INB(PORT_SEQINDX) == i)
      VDMData.aregSEQData[i] = INB(PORT_SEQDATA);
  }
  OUTB(PORT_SEQINDX, bIndex);

  bIndex = INB(PORT_GDCINDX);
  for (i = 0; i < MAX_GDCREGS; i++) {
    OUTB(PORT_GDCINDX, i);
    if (INB(PORT_GDCINDX) == i)
      VDMData.aregGDCData[i] = INB(PORT_GDCDATA);
  }
  OUTB(PORT_GDCINDX, bIndex);

  bIndex = INB(PORT_COLRCRTINDX);
  for (i = 0; i < MAX_CRTREGS; i++) {
    OUTB(PORT_COLRCRTINDX, i);
    if (INB(PORT_COLRCRTINDX) == i)
      VDMData.aregCRTData[i] = INB(PORT_COLRCRTDATA);
  }
  OUTB(PORT_COLRCRTINDX, bIndex);

#endif /* V21YEE05 */

  VDMData.flVDMVideo &= ~VDM_FGND;                      /* force it back */
                                                        /*            end */

  for (i = ATI_START_EXTREGS; i < ATI_END_EXTREGS; i++)
    VDMData.aregATIData[i] = aregATIInit[i-ATI_START_EXTREGS];
  VDMData.aregXGAData[AXGA_OPERATING_MODE] = 1;     /* enable VGA addressing. */
#endif

  /*
  ** Initialize per-VDM GRFXALLOWED bit to global state.
  ** (currently, there is no mechanism to change the
  ** per-VDM state, but we may add one eventually)
  */

  if (flVVD&VVD_GRFXALLOWED)
    VDMData.flVDMVideo |= VDM_GRFXALLOWED;

#ifdef   EGAVGA                                  /*                         */

  /*
  ** Setup codepage buffer from the VDM space.                            
  */

  if ((VDMData.vvMode.vvm_cpID =                 /*                         */
  VDHQuerySysValue(CURRENT_VDM,
                   VDHLSV_CODEPAGEID)) != 0)
  {                                              /*                         */
    VDMData.pCPBuff = VDHAllocDosMem(PAGESIZE);  /*                         */
 /*                                                                         
  * VDMData.ROMint1fSeg = SEGMENTOF16(VDMBase.rb_avpIVT[BIOSINT_VIDEOGRAPH]);
  */
  }                                              /*                         */
#endif                                           /*                         */

    /*
    ** Establish communication with virtual mouse driver
    */

    if (!hvddMouse)
    {
      hvddMouse = VDHOpenVDD(VMD_NAME);

      if (hvddMouse)

        if (!VDHRequestVDD(hvddMouse,
                           hvdm,
                           VMDEVREQ_REGISTER,
                           &vmreg,
                           &vmfunc))
          hvddMouse = FALSE;
    }

#ifdef  GALE                                                            //J-TS00V
  if ( VDMData.flVDMGale ) {                                            //J-TS00V
        /*** Establish communication with virtual font driver ***/      //J-TS00V
    if (!hvddVfontV) {                                                  //J-TS00V
      hvddVfontV = VDHOpenVDD(VFNTV_NAME);                              //J-TS00V
      if (hvddVfontV)                                                   //J-TS00V
        if (!VDHRequestVDD(hvddVfontV, hvdm,                            //J-TS00V
                           VFSYSREQ_GET_ENTRY, NULL, vfvfunc))          //J-TS00V
          hvddVfontV = FALSE;                                           //J-TS00V
    }                                                                   //J-TS00V
        /*** Initialize DBCS handling environment ***/                  //J-TS00V
    if (hvddVfontV)                                                     //J-TS00V
      VVInitDBCSTable();                                                //J-TS00V
  }                                                                     //J-TS00V
                                                                        //J-TS00V
  VDMData.regDACMask = 0xff;        /* FLORA VIDEO BIOS doesn't set */  //J-TS00V
                                    /* this register                */  //J-TS00V
#endif  //GALE                                                          //J-TS00V

  return  TRUE;
}


/***************************************************************************
 *
 * FUNCTION NAME = VVCreateDone()
 *
 * DESCRIPTION   = VDM creation done notification
 *
 *                 This registered subroutine is called each time a new VDM
 *                 successfully complete all parts of VDM creation (see
 *                 VDHInstallUserHook for complete semantics).
 *
 *                 This routine is neccessary because during creation of a
 *                 VDM, an error can occur anywhere within the Create VDM
 *                 path causing confusion over whether the VDM is currently
 *                 foreground.  To insure we can maintain a VDM completion
 *                 state, a per VDM flag will be used to indicate that the
 *                 VDM had successfully complete creation.
 *
 * INPUT         = hvdm -> new VDM
 *
 * OUTPUT        = don't care
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 set a per VDM flag bit to indicate
 *                   VDM creation complete
 *
 **************************************************************************/

VOID EXPENTRY VVCreateDone(HVDM hvdm)            /*                         */
{                                                /*                         */
  VDMData.flVDMXVideo |= VDMX_CREATEDONE;        /*                         */
}                                                /*                         */


#ifdef SVGA                                      /*                         */

/***************************************************************************
 *
 * FUNCTION NAME = vvEditXGAInstance()
 *
 * DESCRIPTION   = Edit XGA Instance
 *
 * INPUT         = PHLE phleEdit
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID PRIVENTRY vvEditXGAInstance(PHLE phleEdit)
{
  register INT i;

  while (phleEdit->hle_port != HLE_ENDPORT)
  {
    for (i = 0; i < 5 && (PORT)phleEdit->hle_pfn[i] != HLE_ENDPORT; i++);

    if (((phleEdit->hle_port & 0xFF00) == 0x2100) &&
        (phleEdit->hle_port & PORTF_SVGA))              /*            */
    {
      phleEdit->hle_port &= ~(0xFFF0|PORTF_NOTRAP);     /* enable IO trap */
      phleEdit->hle_port |= ulXGAInstance;
    }

    (PORT *)phleEdit += i + 2;
  }
}


/***************************************************************************
 *
 * FUNCTION NAME = vvEditXGAInstancePLE()
 *
 * DESCRIPTION   = Edit XGA Instance PLE
 *
 * INPUT         = PPLE ppleEdit
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID PRIVENTRY vvEditXGAInstancePLE(PPLE ppleEdit)
{
  while (ppleEdit->ple_port)
  {
    if ((ppleEdit->ple_port & 0xFF00) == 0x2100)
    {
      ppleEdit->ple_port &= ~0xFFF0;
      ppleEdit->ple_port |= ulXGAInstance;
    }

    ppleEdit++;
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = vvSVGAEditVideoTables()
 *
 * DESCRIPTION   = Called once to do SVGA-specific initialisation
 *
 * INPUT         = ulSVGAAdapterType
 *                 ulSVGAChipType
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/
VOID PRIVENTRY vvSVGAEditVideoTables(ULONG ulSVGAAdapterType, ULONG ulSVGAChipType)
{
  register INT i;
  PHLE phle;
  PRLE parle;
  ULONG ulMaskPosition = 0x1;                                   /*            */

  switch (ulSVGAAdapterType)
  {
    case TSENG_ADAPTER:                                         /*            */
      if (ulSVGAChipType == TSENG_ET4000_CHIP)                  /*            */
      /*           
      ** Enable all appropriate trap list entries by removing NOTRAP flag!
      */
      phle = ahleFgnd;

      while (phle->hle_port != HLE_ENDPORT)
      {
        for (i = 0; i < 5 && (PORT)phle->hle_pfn[i] != HLE_ENDPORT; i++);
        if (phle->hle_port & PORTF_SVGA)
        {
           switch(phle->hle_port & PORT_MASK)
           {
              case PORT_TSENG_SEGSELECT:
              case PORT_HERC_COMPATIBILITY:
              case PORT_TSENG_UNLOCK:
              case 0x3DD:
                 phle->hle_port &= ~PORTF_NOTRAP;               /* mark it as trapped */
                 break;
           }
        }
        (PORT *)phle += i + 2;
      }
      phle = ahleBgnd;

      while (phle->hle_port != HLE_ENDPORT)
      {
        for (i = 0; i < 5 && (PORT)phle->hle_pfn[i] != HLE_ENDPORT; i++);
        if (phle->hle_port & PORTF_SVGA)
        {
           switch(phle->hle_port & PORT_MASK)
           {
              case PORT_TSENG_SEGSELECT:
              case PORT_HERC_COMPATIBILITY:
              case PORT_TSENG_UNLOCK:
              case 0x3DD:
                 phle->hle_port &= ~PORTF_NOTRAP;               /* mark it as trapped */
                 break;
           }
        }
        (PORT *)phle += i + 2;
      }
      break;                                                    /*            */

    case ATI_ADAPTER:                                           /*            */
      /*           
      ** Enable all appropriate trap list entries by removing NOTRAP flag!
      */
      phle = ahleFgnd;

      while (phle->hle_port != HLE_ENDPORT)
      {
        for (i = 0; i < 5 && (PORT)phle->hle_pfn[i] != HLE_ENDPORT; i++);
        if (phle->hle_port & PORTF_SVGA)
        {
           switch(phle->hle_port & PORT_MASK)
           {
              case PORT_ATIVGA_INDX :
              case PORT_ATIVGA_DATA :
                 phle->hle_port &= ~PORTF_NOTRAP;               /* mark it as trapped */
                 break;
           }
        }
        (PORT *)phle += i + 2;
      }
      phle = ahleBgnd;

      while (phle->hle_port != HLE_ENDPORT)
      {
        for (i = 0; i < 5 && (PORT)phle->hle_pfn[i] != HLE_ENDPORT; i++);
        if (phle->hle_port & PORTF_SVGA)
        {
           switch(phle->hle_port & PORT_MASK)
           {
              case PORT_ATIVGA_INDX :
              case PORT_ATIVGA_DATA :
                 phle->hle_port &= ~PORTF_NOTRAP;               /* mark it as trapped */
                 break;
           }
        }
        (PORT *)phle += i + 2;
      }

      parle = arleMemory;
      while (parle->rle_port != 0L)
      {
        if (parle->rle_port & PORTF_SVGA)
        {
           switch(parle->rle_port & PORT_MASK)
           {
              case PORT_ATIVGA_INDX :
                 parle->rle_port &= ~PORTF_NOTRAP;              /* mark it as trapped */
                 break;
           }
        }
        parle++;
      }

      break;
    case CIRRUS_ADAPTER:                                        /*            */
      break;                                                    /*            */
    case WESTERNDIG_ADAPTER:                                    /*            */
      /*            
       *  for GDC, CRT and SEQ entries. This is later used by vvWDLockState
       *  for quick update of the ulregLockState field of the VDMDATA.
       *  ulWDMASK_GDCLOCK = 0x3 means that ausLockCmds[0 and 1] are
       *  locking GDC registers.
      */
      for (i=0;i<ulNumLockCmds;i++,ulMaskPosition<<=1) {        /*            */
           if ((ausLockReg[i] == PORT_GDCINDX) ||
               (ausLockReg[i] == PORT_GDCDATA))
               /* set bit i of the ulWD_MASK_GDCLOCK */
               ulWD_MASK_GDCLOCK |= ulMaskPosition;

           if ((ausLockReg[i] == PORT_COLRCRTINDX) ||
               (ausLockReg[i] == PORT_COLRCRTDATA))
               /* set bit i of the ulWD_MASK_CRTLOCK */
               ulWD_MASK_CRTLOCK |= ulMaskPosition;

           if ((ausLockReg[i] == PORT_SEQINDX) ||
               (ausLockReg[i] == PORT_SEQDATA))
               /* set bit i of the ulWD_MASK_SEQLOCK */
               ulWD_MASK_SEQLOCK |= ulMaskPosition;
      }
      break;              

    case VIDEO7_ADAPTER:

      /*
      **  Note: the entries in ahleFgnd are variable length but this
      **  relies on there being only one match for the Misc Output
      **  reg. We ensure here that VVWriteMiscOutFgnd doesn't get
      **  hooked for VIDEO7. The fix for IBM h/ware causes screen
      **  disturbances on the HT208/HT209 chipsets.
      */

      phle = ahleFgnd;

      while (phle->hle_port != HLE_ENDPORT)
      {
        for (i = 0; i < 5 && (PORT)phle->hle_pfn[i] != HLE_ENDPORT; i++);

        if ((phle->hle_port & PORT_MASK) == PORT_STATUS0)
        {
          phle->hle_port |= PORTF_NOTRAP;
          break;
        }

        (PORT *)phle += i + 2;
      }

      break;

    case IBM_ADAPTER:

      /*
      **  We need to find the current instance of the XGA/IBMSVGA
      */

      _asm
      {
                mov     edx,2100h       ; locate the register base
        lp1:
                in      al,dx           ; read register base
                mov     ah,al
                mov     al,07h          ; write out '07'
                out     dx,al
                in      al,dx           ; read back and save
                mov     cl,al
                mov     al,ah           ; replace original value
                out     dx,al
                cmp     cl,05h          ; if value retained then
                je      foundit         ;    speedway/XGA on board
                add     dx,10h          ;
                cmp     dx,2180h
                jb      lp1             ;  retry
                xor     dx,dx           ;  no SPEEDWAY found
        foundit:
                mov     ulXGAInstance,edx
      }

      if (ulXGAInstance)
      {
        vvEditXGAInstance(ahleFgnd);
        vvEditXGAInstance(ahleBgnd);
        vvEditXGAInstancePLE(apleAll);                          /*            */
        vvEditXGAInstancePLE(apleNoTrap);                       /*            */
      }

      break;
  }

}

#endif


/***************************************************************************
 *
 * FUNCTION NAME = VVSetFgnd()
 *
 * DESCRIPTION   = VDM foreground notification
 *
 *                 This registered subroutine is called each time a VDM is
 *                 switched to foreground.  It adjusts the level of
 *                 virtualization so that I/O commands are directed to the
 *                 hardware instead of being virtualized (see
 *                 VDHInstallUserHook for complete semantics).
 *
 * INPUT         = hvdm -> new foreground VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 if no ownership
 *                   return
 *                 update all state information
 *                 set foreground mode
 *                 disable video signal
 *                 update physical video memory with virtual
 *                 if mouse pointer enabled
 *                   draw pointer
 *                 update physical registers with virtual state
 *                 enable video signal
 *
 *                 thaw VDM if previously frozen
 *                   due to unsupported background access
 *                 arm context hook to grow buffer/enable pages
 *
 *
 **************************************************************************/

VOID EXPENTRY VVSetFgnd(register HVDM hvdm)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  INT i;                                         /*                         */

  /*
  ** If we own the device and the VDM is not already foreground
  */

  if (pvd->flVDMXVideo&VDMX_DEVOWNER && !(pvd->flVDMVideo&VDM_FGND))
  {
    RequestMutexSem(pvd->hmxVideoState);
    VDHFreezeVDM(hvdm);

#ifdef   VGA                                     /*                         */

    if (pvd->flVDMXVideo&VDMX_SAVERESTORE)
    {                                            /*                         */
#endif                                           /*                         */

      if (!(pvd->flVDMXVideo&VDMX_ONDEMAND) && !vvGrowBuffer(hvdm,
                                                             ALL_PLANES,
                                                             GROW_MAXIMUM,
                                                             BANK0))
      {                                          /*                         */
        vvAddEvent(hvdm,
                   VVDEVENT_SWITCHERROR,
                   NULL,
                   0);
        flVVD |= VVD_VRAMISTOAST;           /* tell PM to repaint           */
        goto error;
      }

#ifdef   EGAVGA

      /*
      ** Since we're foreground, we own the controller by default
      */

      hvdmController = hvdm;
#endif

      /*
      ** Update our assumptions about the state of the VDM
      */

#ifdef SVGA
      vvUnLockSVGARegisters();                          /*            */
      /*
      **            If 2F processing enabled, don't save/restore the
      ** adapter's video state.
      */
      if (!(pvd->flVDMXVideo & VDMX_INT2F))
#endif
      vvUpdateAll(hvdm,
                  TRUE);
      pvd->flVDMVideo |= VDM_FGND;

      /*
      ** Turn the screen off while we're updating things;
      ** in the MONO (secondary display) case, there's no need to if
      ** the display hasn't been initialized yet .
      */

#ifdef   MONO
      /*                                                                73042
      ** Enable the display                                             73042
      */                                                             /* 73042 */

      vvEnableDisplay(hvdm);                                         /* 73042 */

      if (pvd->mstateVideo)
#endif

#ifdef SVGA
      /*
      **            If 2F processing enabled, don't save/restore the
      ** adapter's video state.
      */
      if (!(pvd->flVDMXVideo & VDMX_INT2F))
      {
#endif
#ifdef   VGA                                     /*                         */

      /*
      ** Restore physical latches, before I/O state is restored
      */

      vvRestoreLatches(hvdm,
                    FALSE);

      /*
      ** Update physical registers with virtual I/O state
      */

      vvRestoreIOState(hvdm);
#endif
      vvDisableDisplay(hvdm);

#ifdef   SVGA
      {
        INT iBankNo,iBankEnd = 1;
        BOOL flTransferDone, bOperMode;         /*            */
        register ULONG nBytes,nRows,nBitsPixel;

        if ((ulSVGAAdapterType == IBM_ADAPTER) &&  /*            */
            (pvd->mstateVideo == MEMORY_GRFX256))  /*            */
        { /* Reset VGA address enable on Speedway to allow bank setting in transfer */
           bOperMode = INB(ulXGAInstance);
           if (bOperMode & 0x10){
               bOperMode &= 0xFE;
               OUTB(ulXGAInstance,bOperMode);
           }
        }                                       /*            */

        if ((pvd->mstateVideo == MEMORY_GRFX) ||                          /*            */
            (pvd->mstateVideo == MEMORY_GRFX256))                         /*            */
        {
            iBankEnd = vvMaxBanks(hvdm);                                  /*            */
                                                                          /*            */
            if (ulSVGAAdapterType == S3_ADAPTER)                          /*            */
               v8514EnableBankAdd(hvdm);
        }
        /*
        ** Special case mode 13 with CHAIN4 bit reset. Treat it as
        ** a planar mode and update its page states to include all the
        ** planes.                                                
        */

        if((pvd->ulBIOSMode&~BIOSVINFO_DONTCLEAR) ==
            BIOSVMODE_CO320X200X256 &&
           !(pvd->aregSEQData[REG_SEQMEMMODE] & SEQMEM_CHAIN4))
           vvPrepareForTransfer(hvdm,TRUE,iBankEnd);                      /*            */

        if (pvd->flVDMXVideo & VDMX_ENHANCEDMODE)                         /*            */
            flTransferDone = vvTransferLinearBuffer(hvdm, iBankEnd, TRUE);/*            */
#ifdef  GALE                                                            //J-TS00V
        else if ((pvd->flVDMGale) &&                                    //J-TS00V
                 ((pvd->ulBIOSMode == 0x03) ||                          //J-TS00V
                  (pvd->ulBIOSMode == 0x73)))                           //J-TS00V
            flTransferDone = TRUE;                                      //J-TS00V
#endif  //GALE                                                          //J-TS00V
        else for (iBankNo=0; iBankNo < iBankEnd; iBankNo++)               /*            */
            flTransferDone = vvTransferBuffer(hvdm, iBankNo, TRUE);       /*            */

        /*
        ** Update physical video memory with virtual memory
        */

        if ((!flTransferDone) &&
            !(pvd->flVDMVideo & VDM_MODECHANGING))                       /*            */
        {
          vvAddEvent(hvdm,
                     VVDEVENT_SWITCHERROR,
                     NULL,
                     0);
          flVVD |= VVD_VRAMISTOAST;      /* tell PM to repaint            */
          goto error;
        }

      }

#else

   #ifdef   VGA
      /*
      ** Clear Aperture Control setting for all XGAs                      
      */

      if  (flXGAPresent)                    /* XGA present                */
      {                                     /*                            */
        for (i = 0; i < 8; i++)             /* do for all XGAs            */
        {                                   /*                            */
          OUTB(0x2101|((i << 4)&0x00f0),    /* set 21x1=00                */
               0);                          /*                            */
        }                                   /* endfor                     */
      }                                     /* end XGA test               */
   #endif

      /*
      ** Update physical video memory with virtual memory
      */

#ifdef  GALE                                                            //J-TS00V
      if ((!pvd->flVDMGale) ||                                          //J-TS00V
          ((pvd->ulBIOSMode != 0x03) &&                                 //J-TS00V
           (pvd->ulBIOSMode != 0x73)))                                  //J-TS00V
#endif  //GALE                                                          //J-TS00V
      if (!vvTransferBuffer(hvdm,
                            0,
                            TRUE))
      {
        vvAddEvent(hvdm,
                   VVDEVENT_SWITCHERROR,
                   NULL,
                   0);
        flVVD |= VVD_VRAMISTOAST;          /* tell PM to repaint            */
        goto error;
      }
#endif

#ifdef   EGAVGA

      /*
      ** Restore physical latches, before I/O state is restored
      */

      vvRestoreLatches(hvdm,
                       FALSE);
#endif

      /*
      ** Update physical registers with virtual I/O state
      */

#ifdef   SVGA
      pvd->flVDMXVideo |= VDMX_RESTOREBTDAC;        /* restore DAC           */
#endif
      vvRestoreIOState(hvdm);
#ifdef  SVGA
      pvd->flVDMXVideo &= ~VDMX_RESTOREBTDAC;       /* all done              */
#endif

#ifdef  GALE                                                            //J-TS00V
      if (pvd->flVDMGale) {                                             //J-TS00V
        flVVD |= VVD_VRAMISTOAST;       //tell PM to repaint            //J-TS00V
                                                                        //J-TS00V
        if (((pvd->ulBIOSMode == 0x03) ||                               //J-TS00V
             (pvd->ulBIOSMode == 0x73)) &&                              //J-TS00V
            (pvd->flVDMXVideo & VDMX_CREATEDONE) &&                     //J-TS00V
            !(pvd->flVDMVideo & VDM_MODECHANGING))                      //J-TS00V
          VVRedrawScreen(hvdm);                                         //J-TS00V
      }                                                                 //J-TS00V
#endif  //GALE                                                          //J-TS00V
#ifdef  VTEXT                                                           //J-TS00V
      if (pvd->GaleData.flVtext & VDMV_VTEXT_INSTALLED)                 //J-TS00V
        flVVD |= VVD_VRAMISTOAST;       //tell PM to repaint            //J-TS00V
#endif  //VTEXT                                                         //J-TS00V

      pvd->PtrData.fPtrFrozenVideo--;
      AssertTRUE(pvd->PtrData.fPtrFrozenVideo >= 0);

      /*
      ** Put pointer back on screen, if one exists
      */

      if (!pvd->PtrData.fPtrFrozenVideo && pvd->PtrData.flPtrVideo&PTR_ACTIVE)
      {
        pvd->flVDMVideo |= VDM_IOUPDATED;
        vvPtrDraw(hvdm,
                  pvd->PtrData.xPtrVideo,
                  pvd->PtrData.yPtrVideo);
        pvd->flVDMVideo &= ~VDM_IOUPDATED;
      }

      /*
      ** Enable the screen if there's something to look at yet
      */

      if (pvd->mstateVideo)
        vvEnableDisplay(hvdm);

#ifdef SVGA
      }                                                 /*            */
      else
      {
        pvd->PtrData.fPtrFrozenVideo--;                 /*            */
        AssertTRUE(pvd->PtrData.fPtrFrozenVideo >= 0);

        /*
        ** Put pointer back on screen, if one exists
        */

        if (!pvd->PtrData.fPtrFrozenVideo && pvd->PtrData.flPtrVideo&PTR_ACTIVE)
        {
          pvd->flVDMVideo |= VDM_IOUPDATED;
          vvPtrDraw(hvdm,
                  pvd->PtrData.xPtrVideo,
                  pvd->PtrData.yPtrVideo);
          pvd->flVDMVideo &= ~VDM_IOUPDATED;
        }
        vvDisableDisplay(hvdm);
      }
      /*
      ** If VDM is started in the bgnd in a way that VRAMISTOAST flag is
      ** reset before the first foreground for the VDM happens, the
      ** desktop will not be repainted after our next Bgnd switch,
      ** although we are not capable of restoring its VRAM state.
      ** To circumvent this, on our first foreground, we make sure
      ** that VRAM is toasted.
      */

      if(pvd->flVDMX2Video & VDMX2_FIRSTFGND)              /*            */
      {
          flVVD |= VVD_VRAMISTOAST;      /* tell PM to repaint */
          pvd->flVDMX2Video &= ~VDMX2_FIRSTFGND;
      }
#endif
      /*
      ** Make an appointment to set up VDM's VRAM mappings, etc
      */

      if (!vdhBTS(&pvd->flVDMVideo,
                  LOG2(VDM_FGNDHOOK)))
        VDHArmContextHook(pvd->hhookFgndContext,
                          hvdm);
#ifdef SVGA                                                     /*           start*/
      if (ulSVGAAdapterType == S3_ADAPTER)
      {
        /*
        ** Release the IOOWNED bit, mark it unblocked.
        */
        v8514UnlockIO(hvdm);
        vdhBTR(&pvd->flVDMX2Video,
              LOG2(VDMX2_8514BLOCKED));
      }
      /*
      ** If 2F registered and this is not creation, delay the
      ** return from the SetFgnd until INT 2F is finished.
      ** This is to ensure proper order of the
      ** notifications and to avoid nesting. WINOS2 doesn't handle
      ** nesting or out of order notifications very well.
      */
      if ((pvd->flVDMXVideo & VDMX_INT2F) &&
          (pvd->flVDMVideo & VDM_IOINIT))
      {
        pvd->flVDMVideo &= ~VDM_FROZEN;
        ReleaseMutexSem(pvd->hmxVideoState);
        /*
        ** Make sure we thaw the instance completelly.
        */
        while (VDHIsVDMFrozen(hvdm))
          VDHThawVDM(hvdm);

        /*
        ** Make sure VDM is not blocked as idle.
        ** Block on the 2F semaphore until either timeout occurs or
        ** 2F successfuly returns.
        */
        VDHWakeIdle(hvdm);
        VDHResetEventSem(pvd->hevInt2FDelaySwitch);
        VDHWaitEventSem(pvd->hevInt2FDelaySwitch,MAX_VDM_WAIT);
        VDHThawVDM(hvdm);
        return;
      }
#endif                                                          /*           end*/
      /*
      ** We undid the screen-switch freeze, but there may be others
      */
      vvThawVDM(hvdm);

#ifdef   VGA                                     /*                         */
    }                                            /*                         */

    else
    {                                            /*                         */
      pvd->flVDMVideo |= VDM_FGND;               /*                         */

      /*
      ** Send INT 2F if required                                            
      */

      if (!vdhBTS(&pvd->flVDMVideo,
                  LOG2(VDM_FGNDHOOK)))           /*                         */
        VDHArmContextHook(pvd->hhookFgndContext,
                          hvdm);                 /*                         */
    }                                            /*                         */
#endif                                           /*                         */
error:
    VDHThawVDM(hvdm);
    ReleaseMutexSem(pvd->hmxVideoState);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetBgnd()
 *
 * DESCRIPTION   = VDM background notification
 *
 *                 This registered subroutine is called each time a VDM is
 *                 switched to background.  It adjusts the level of
 *                 virtualization so that I/O commands are virtualized
 *                 instead of being allowed to go to the hardware (see
 *                 VDHInstallUserHook for complete semantics).
 *
 *                 Note that we also leave the video signal OFF after we are
 *                 done exchanging VRAM contents.  This is because, although
 *                 VRAM for the previous session is now restored, we do not
 *                 know what the I/O state for that session was.
 *                 Furthermore, that session may not be the one returning to
 *                 the foreground anyway.  Hence, it is best to leave the
 *                 screen disabled.
 *
 * INPUT         = hvdm -> new background VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 if no ownership
 *                   return
 *                 update all virtual regs from physical state
 *                 disable video signal
 *
 *                 if mouse pointer enabled
 *                   remove pointer
 *                 save physical video memory to virtual
 *                 set background mode
 *                 thaw VDM if previously frozen
 *                   due to error to growing background buffer
 *                 arm context hook to shrink background buffer
 *
 **************************************************************************/

VOID EXPENTRY VVSetBgnd(register HVDM hvdm)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  INT i;                                         /*                         */
  BYTE bOperMode;                                /*                         */

#ifdef   SVGA
  INT iBankNo,iBankEnd = 1;
  BOOL flFrozenOnEntry = FALSE;                  /*                         */
  register ULONG nBytes,nRows,nBitsPixel;
  BOOL flWindow = FALSE;                           /*            */
#endif

  /*
  ** If we own the device and the VDM is in the
  ** foreground *or* does not have a valid video state yet.
  */

  if (pvd->flVDMXVideo&VDMX_DEVOWNER && (pvd->flVDMVideo&VDM_FGND ||
  !pvd->mstateVideo))
  {
    RequestMutexSem(pvd->hmxVideoState);
#ifdef SVGA
    /*
    ** Make sure that engine has completed all pending commands           
    ** before freezing.
    */
    if ((ulSVGAAdapterType == S3_ADAPTER) &&
        (pvd->flVDMXVideo&(VDMX_SAVERESTORE|VDM_FGND) ==
         VDMX_SAVERESTORE|VDM_FGND))
      v8514WaitOnEngine(hvdm);
    /*
    ** Query the frozen state in order to restore it.
    */
    if (VDHIsVDMFrozen(hvdm))
      flFrozenOnEntry = TRUE;                    /*                         */
    else                                         /*                         */
#endif
    VDHFreezeVDM(hvdm);

#ifdef   VGA                                     /*                         */

    if (pvd->flVDMXVideo&VDMX_SAVERESTORE)
    {                                            /*                         */
#endif                                           /*                         */

      /*
      ** If there's a foreground state to save, save it
      */

      if (pvd->flVDMVideo&VDM_FGND)
      {
#ifdef  XVIO                                                            //J-TS00V
        if ((pvd->flVDMGale) &&                                         //J-TS00V
            !(pvd->flVDMVideo & VDM_DYING) &&                           //J-TS00V
            (pvd->flVDMVideo & VDM_STATEINIT)) {                        //J-TS00V
          VXSCROLL vxScroll;                                            //J-TS00V
                                                                        //J-TS00V
          vxSetStatus(hvdm, XVIO_STATUS_XVIOUPDATING, XVIO_SET_FLAG);   //J-TS00V
          ReleaseMutexSem(pvd->hmxVideoState);                          //J-TS00V
          vxFlushEvent(hvdm, VXEVENT_MODE,   0);                        //J-TS00V
          vxFlushEvent(hvdm, VXEVENT_LVB,    0);                        //J-TS00V
          vxFlushEvent(hvdm, VXEVENT_STRING, 0);                        //J-TS00V
          vxFlushEvent(hvdm, VXEVENT_CURSOR, 0);                        //J-TS00V
          vxScroll.vxs_rcl.yTop    = 0;                                 //J-TS00V
          vxScroll.vxs_rcl.xLeft   = 0;                                 //J-TS00V
          vxScroll.vxs_rcl.yBottom = -1;                                //J-TS00V
          vxScroll.vxs_rcl.xRight  = -1;                                //J-TS00V
          vxScroll.vxs_fill        = 0x2000;                            //J-TS00V
          vxScroll.vxs_nRows       = 1;                                 //J-TS00V
          vxAddEvent(hvdm, VXEVENT_HIDE,                                //J-TS00V
                     (PPVOID)SSToDS(&vxScroll), XEVENT_FLUSH);          //J-TS00V
          vxAddEvent(hvdm, VXEVENT_BACKGROUND,                          //J-TS00V
                     NULL, XEVENT_FLUSH);                               //J-TS00V
          RequestMutexSem(pvd->hmxVideoState);                          //J-TS00V
          vxSetStatus(hvdm, XVIO_STATUS_XVIOUPDATING, XVIO_RESET_FLAG); //J-TS00V
        }                                                               //J-TS00V
#endif  //XVIO                                                          //J-TS00V

     #ifdef SVGA
        vvUnLockSVGARegisters();

      /*
      **            If 2F processing enabled, don't save/restore the
      ** adapter's video state.
      */
      if (!(pvd->flVDMXVideo & VDMX_INT2F))
      {
     #endif
       #ifdef   VGA                                             /*            */
//      if (pvd->flVDMXVideo & VDMX_NOIOTRAPPING)               /*            */
          vvSaveDACState(hvdm);
       #endif

        /*
        ** Update our assumptions about the state of the VDM
        */

        vvUpdateAll(hvdm,TRUE);

        /*
        ** Turn the screen off while we're updating things
        */

        vvDisableDisplay(hvdm);

        /*
        ** Freeze the pointer
        */

        pvd->PtrData.fPtrFrozenVideo++;

        /*
        ** Take pointer off the screen, if one exists
        */

        if (pvd->PtrData.flPtrVideo&PTR_ACTIVE)
          vvPtrErase(hvdm);

#ifdef   EGAVGA

   #ifdef   VGA

      #ifdef   SVGA

        if ((ulSVGAAdapterType == IBM_ADAPTER) &&  /*            */
            (pvd->mstateVideo == MEMORY_GRFX256))  /*            */
        {
           bOperMode = INB(ulXGAInstance);
           if (bOperMode & 0x10 )
           {/* Reset VGA address enable on Speedway to allow bank setting in ext mode transfer */
                bOperMode &= 0xFE;
                OUTB(ulXGAInstance,bOperMode);
           }
        }
        else                                    /*            */
      #endif

          /*
          ** Clear Aperture Control setting for all XGAs
          */

          if (flXGAPresent)                        /*                         */
            for (i = 0; i < 8; i++)
            {
              OUTB(0x2101|((i << 4)&0x00f0),
                   0);
            }                                      /* endfor                  */
   #endif

        /*
        ** Save the physical latches, now that I/O state can be changed
        */

        vvSaveLatches(hvdm,
                      FALSE);
#endif

#ifdef   SVGA

        if (!(pvd->flVDMVideo & VDM_WINDOWED) &&
            ((pvd->mstateVideo == MEMORY_GRFX) ||               /*            */
             (pvd->mstateVideo == MEMORY_GRFX256)))             /*            */
          {
            iBankEnd = vvMaxBanks(hvdm);                           /*            */
            if (ulSVGAAdapterType == S3_ADAPTER)                  /*            */
              v8514EnableBankAdd(hvdm);
          }

        /*
        ** Special case mode 13 with CHAIN4 bit reset. Treat it as
        ** a planar mode and update its page states to include all the
        ** planes.                                                
        */

        if((pvd->ulBIOSMode&~BIOSVINFO_DONTCLEAR) ==
            BIOSVMODE_CO320X200X256 &&
           !(pvd->aregSEQData[REG_SEQMEMMODE] & SEQMEM_CHAIN4))
           vvPrepareForTransfer(hvdm,FALSE,iBankEnd);          /*            */

        if (pvd->flVDMXVideo & VDMX_ENHANCEDMODE)               /*            */
            vvTransferLinearBuffer(hvdm, iBankEnd, FALSE);      /*            */
#ifdef  GALE                                                            //J-TS00V
        else if ((pvd->flVDMGale) &&                                    //J-TS00V
                 ((pvd->ulBIOSMode == 0x03) ||                          //J-TS00V
                  (pvd->ulBIOSMode == 0x73)))                           //J-TS00V
            ;   /* nop */                                               //J-TS00V
#endif  //GALE                                                          //J-TS00V
        else for (iBankNo=0; iBankNo < iBankEnd; iBankNo++)     /*            */
            vvTransferBuffer(hvdm, iBankNo, FALSE);             /*            */

        (*apfnSVGASetBank[ulSVGAAdapterType])(hvdm,
                                              BANK0,
                                              TRUE);

#else

        /*
        ** Update virtual video memory with physical memory
        */

#ifdef  GALE                                                            //J-TS00V
        if ((!pvd->flVDMGale) ||                                        //J-TS00V
            ((pvd->ulBIOSMode != 0x03) &&                               //J-TS00V
             (pvd->ulBIOSMode != 0x73)))                                //J-TS00V
#endif  //GALE                                                          //J-TS00V
        vvTransferBuffer(hvdm,
                         0,
                         FALSE);
#endif

#ifdef  XVIO                                                            //J-TS00V
          if (pvd->flVDMGale)       /* clear XVIO PS */                 //J-TS00V
              memset(pvd->XVIOData.GaleXVIOLVB, 0, GALE_LVB_SIZE);      //J-TS00V
#endif  //XVIO                                                          //J-TS00V

#ifdef   EGAVGA

   #ifdef   VGA                                  /*                         */
          if (pvd->mstateVideo <= MEMORY_TEXT)   /*                         */
            vvRestoreIOState(hvdm);              /*                         */
   #endif                                        /*                         */
#endif

#ifdef SVGA
        }                                        /*                          */
        else                                     /* INT 2F enabled */
        {                                        /*            start */
           /*
           ** Freeze the pointer
           */

           pvd->PtrData.fPtrFrozenVideo++;

           /*
           ** Take pointer off the screen, if one exists
           */

           if (pvd->PtrData.flPtrVideo&PTR_ACTIVE)
             vvPtrErase(hvdm);                   /*            end */

           vvDisableDisplay(hvdm);
           flVVD |= VVD_VRAMISTOAST;             /* tell PM to repaint           */
        }
#endif

#ifdef   EGAVGA
        if (hvdmController == hvdm)
          vvFreeController(hvdm);                /*                         */
#endif

        /*
        ** Reenable display if the VDM failed to complete create
        */

        if (!(pvd->flVDMXVideo&VDMX_CREATEDONE))
        {                                        /*                         */

#ifdef   EGAVGA                                  /*                         */
           pvd->regATCIndx = ATCPAL_ENABLE;      /*                         */
#endif                                           /*                         */
           vvEnableDisplay(hvdm);                /*                         */
        }                                        /*                         */

#ifdef VGA
        if (flXGAPresent && (pvd->flVDMVideo & VDM_FGND))   /*              */
          vvDisableVRAM(hvdm);
#endif

        pvd->flVDMVideo &= ~VDM_FGND;
      }
#ifdef  XVIO                                                            //J-TS00V
      else {                                                            //J-TS00V
        if (pvd->flVDMGale)  {                                          //J-TS00V
          vxSetStatus(hvdm, XVIO_STATUS_XVIOUPDATING, XVIO_SET_FLAG);   //J-TS00V
          ReleaseMutexSem(pvd->hmxVideoState);                          //J-TS00V
          vxAddEvent(hvdm, VXEVENT_BACKGROUND, NULL, NULL);             //J-TS00V
          RequestMutexSem(pvd->hmxVideoState);                          //J-TS00V
          vxSetStatus(hvdm, XVIO_STATUS_XVIOUPDATING, XVIO_RESET_FLAG); //J-TS00V
        }                                                               //J-TS00V
#endif  //XVIO                                                          //J-TS00V
#ifdef SVGA
#ifndef XVIO                                                            //J-TS00V
      else                                       /* It was not foreground */
#endif  //XVIO                                                          //J-TS00V
        flWindow = TRUE;                         /*            */
#endif
#ifdef  XVIO                                                            //J-TS00V
      }                                                                 //J-TS00V
#endif  //XVIO                                                          //J-TS00V

      /*
      ** For dying VDMs, this is all we need to do (saves time)
      */

      if (!(pvd->flVDMVideo & VDM_DYING))        /*                         */
      {

        /*
        ** Make an appointment to set up VDM's VRAM mappings, etc
        */

        if (!vdhBTS(&pvd->flVDMVideo,
                    LOG2(VDM_BGNDHOOK)))
        {
          VDHWakeIdle(hvdm);                              /*            */
          VDHArmContextHook(pvd->hhookBgndContext,
                            hvdm);
        }

        /*
        ** Note that if the VDM is in MEMORY_GRFX mode, then we should
        ** leave it frozen, and let either (1) PM thaw it when PM switches
        ** foreground, or (2) let our own SetFgnd thaw him later.
        */

#ifdef  GALE                                                            //J-TS00V
      if(!pvd->flVDMGale ||                                             //J-TS00V
         ((pvd->ulBIOSMode != 0x03) && (pvd->ulBIOSMode != 0x73)))      //J-TS00V
#endif  //GALE                                                          //J-TS00V
#ifdef  VTEXT                                                           //J-TS00V
       if (!(pvd->GaleData.flVtext & VDMV_SUPPORTED_TEXT_MODE))         //J-TS00V
#endif  VTEXT                                                           //J-TS00V
        if (pvd->mstateVideo == MEMORY_GRFX && pvd->flVDMXVideo&VDMX_DSPOWNER)
          vvFreezeVDM(hvdm,
                      FALSE);

#ifdef  SVGA
        /*
        ** Depending on the INT 2F, take action.
        */
        if (pvd->flVDMVideo & VDM_IOINIT)           /*                         */
           vvSVGASetBgnd(hvdm);                     /*                         */
        if (ulSVGAAdapterType == S3_ADAPTER)
        {
          /*
          ** Don't allow any enhanced access in the background.
          */
          v8514LockIO(hvdm);
        }
#endif
      }
#ifdef SVGA
      /*
      ** Cleanup is executed only for full screen VDM's.
      */
      if (!flWindow)
        vvSVGAFixSetBgnd(hvdm);                  /*                         */
#endif
#ifdef   VGA                                     /*                         */
    }

    else                                         /* nothing to save restore */
    {                                            /*                         */
      pvd->flVDMVideo &= ~VDM_FGND;              /*                         
                                                                            */

      /*** Send INT 2F if required **                                       */

      if (!vdhBTS(&pvd->flVDMVideo,
                  LOG2(VDM_BGNDHOOK)))           /*                         */
        VDHArmContextHook(pvd->hhookBgndContext,
                          hvdm);                 /*                         */
    }                                            /*                         */
#endif                                           /*                         */

#ifdef SVGA
    if (!flFrozenOnEntry)                        /*                         */
#endif
    VDHThawVDM(hvdm);                            /*                          */
    ReleaseMutexSem(pvd->hmxVideoState);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = VVChangeCodePage()
 *
 * DESCRIPTION   = VDM codepage change notification
 *
 *                 This registered subroutine is called each time a VDM
 *                 changes codepages.  It is always called in the context of
 *                 the VDM that changed.
 *
 * INPUT         = cpID == codepage ID
 *
 * OUTPUT        = TRUE if codepage supported, FALSE if not
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

BOOL EXPENTRY VVChangeCodePage(ULONG cpID)
{

#ifdef   EGAVGA

#ifdef  GALE                                                            //J-TS00V
  register PCodePages pcp;                                              //J-TS00V
  pcp = CodePagesTable;                                                 //J-TS00V
                                                                        //J-TS00V
  if (!VDMData.flVDMGale)                                               //J-TS00V
#endif  //GALE                                                          //J-TS00V
  if (!vvLoadCodePageFont())
    return  FALSE;
#endif

  VDMData.vvMode.vvm_cpID = cpID;
#ifdef  GALE                                                            //J-TS00V
  while(pcp->cp_cp2) {                                                  //J-TS00V
    if( cpID == pcp->cp_cp2 ) {                                         //J-TS00V
      VDMData.vvMode.vvm_cpID = pcp->cp_cp1;                            //J-TS00V
      break;                                                            //J-TS00V
    }                                                                   //J-TS00V
    pcp++;                                                              //J-TS00V
  }                                                                     //J-TS00V
#endif  //GALE                                                          //J-TS00V
  vvUpdateModeData(CURRENT_VDM);
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVChangeTitle()
 *
 * DESCRIPTION   = VDM title change notification
 *
 *                 This registered subroutine is called each time a VDM
 *                 changes its title.  It is always called in the context of
 *                 the VDM that changed.
 *
 * INPUT         = pszTitle -> new title (NULL if back to default)
 *
 * OUTPUT        = TRUE (always indicate success)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

BOOL EXPENTRY VVChangeTitle(PSZ pszTitle)
{
  vvAddEvent(CURRENT_VDM,
             VVDEVENT_TITLECHANGE,
             pszTitle,
             0);
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVDestroy()
 *
 * DESCRIPTION   = VDM termination notification
 *
 *                 This registered subroutine is called each time an
 *                 existing VDM is destroyed (see VDHInstallUserHook for
 *                 complete semantics).
 *
 *                 The only work we need to perform at this time is freeing
 *                 the virtual memory buffer(s).  We'll let the process
 *                 termination code throw away semaphore info, and any other
 *                 per-task data.
 *
 * INPUT         = hvdm -> dying VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID EXPENTRY VVDestroy(HVDM hvdm)
{
  VDHSEMSTATE vss;                               /*                         */

  RequestMutexSem(hmxWindowedEvent);

  /*
  ** If this VDM died windowed or with focus, clean up
  */

  if ((VDMData.flVDMVideo&VDM_WINDOWED) &&       /*                         */
     (!(VDMData.flVDMXVideo&VDMX_SEAMLESS)))     /*                         */
  {                                              /*                         */
    /*
    ** If the dying windowed VDM has the VGA Controller, remove it.
    ** So we don't mistakenly touch its VDM data after the VDM is gone
    */
   #ifdef EGAVGA
    if (hvdm == hvdmController)                  /*                         */
        vvFreeController(hvdm);                  /*                         */
   #endif
    nWindowedVDMs--;
  }                                              /*                         */

  if (hvdm == hvdmFocus)
    hvdmFocus = NULL;

  if (hvdm == hvdmUpdate)
    hvdmUpdate = NULL;

  if (VDMData.flVDMVideo&VDM_PMWINDOWED)
    nPMWindowedVDMs--;

  if (VDMData.flVDMVideo&VDM_MINIMIZED)
    nMinWindowedVDMs--;

  while (VDMData.flEventsPending)
  {
    VDMData.flEventsPending &= ~(1 << vdhBSF(VDMData.flEventsPending));
    nWindowedEvents--;
  }

  /*
  ** Make sure VDM's list-entries are removed from all lists
  */

  REMOVEENTRY(hvdm,
              Active);
  ReleaseMutexSem(hmxWindowedEvent);

#ifdef   EGAVGA
  vvFreeAllPhysPages(hvdm,
                     TRUE);

/*  if (hvdm == hvdmController)                                             */
/*      hvdmController = NULL;                                              */

#endif

  /*
  ** Reset VRAMISTOAST bit after destruction of a foreground              
  */

  /*
  ** XGA application                                                      
  */

  if ((VDMData.flVDMVideo&VDM_FGND) && (flVVD&VVD_REPAINT))
  {
    flVVD &= ~VVD_REPAINT;
  }                                              /* endif                   */

  /*
  ** Even for dying fgnd VDMs, we should restore previous VRAM
  */

  VDMData.flVDMVideo |= VDM_DYING;
  VVSetBgnd(hvdm);

  /*
  ** Free buffer
  */

  vvShrinkBuffer(CURRENT_VDM,
                 TRUE);

  /*
  ** Note: no concept of per-VDM semaphores; must free ourselves
  */

  if (VDMData.hmxVideoState)
  {
    VDHQuerySem(VDMData.hmxVideoState,
                SSToDS(&vss));                   /*                         */

    if (vss.vss_fOwned)
    {                                            /*                         */
      RequestMutexSem(VDMData.hmxVideoState);    /*                         */
      ReleaseMutexSem(VDMData.hmxVideoState);    /*                         */
    }
    DestroyMutexSem(VDMData.hmxVideoState);
  }

  if (VDMData.hmxWindowedState)
    DestroyMutexSem(VDMData.hmxWindowedState);

  if (VDMData.hevFreezeThaw)
    DestroyEventSem(VDMData.hevFreezeThaw);

#ifdef  SVGA
  if (VDMData.hevInt2FDelaySwitch)
    DestroyEventSem(VDMData.hevInt2FDelaySwitch);   /*                         */
  if (VDMData.hev8514WakeUp)
    DestroyEventSem(VDMData.hev8514WakeUp);         /*            */
  if (VDMData.hev8514Busy)
    DestroyEventSem(VDMData.hev8514Busy);           /*            */
#endif

  if (VDMData.hevShieldSynced)
    DestroyEventSem(VDMData.hevShieldSynced);
}

#ifdef   PROPERTIES

/***************************************************************************
 *
 * FUNCTION NAME = VVSetInt10Emulation
 *
 * DESCRIPTION   = Set per-VDM INT 10h emulation flag
 *
 *                 This routine is called when the user alters an existing
 *                 VDM's INT 10h emulation "advanced property" setting.
 *
 * INPUT         = op - operation to perform (set)
 *                 hvdm - target VDM
 *                 cb - length of value
 *                 psz - ptr to BOOL value
 *
 * OUTPUT        = returns 0 (no error)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

ULONG EXPENTRY VVSetInt10Emulation(ULONG op,HVDM hvdm,ULONG cb,PSZ psz)
{
  AssertTRUE(op == VDHPROP_SET);
  SETBIT(pVDMData(hvdm)->flVDMXVideo,
         VDMX_INT10EMULATE,
         (BOOL)psz);
  return 0;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetRetraceEmulation
 *
 * DESCRIPTION   = Set per-VDM retrace emulation flag
 *
 *                 This routine is called when the user alters an existing
 *                 VDM's horz/vert retrace emulation "advanced property"
 *                 setting.
 *
 * INPUT         = op - operation to perform (set)
 *                 hvdm - target VDM
 *                 cb - length of value
 *                 psz - ptr to BOOL value
 *
 * OUTPUT        = returns 0 (no error)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

ULONG EXPENTRY VVSetRetraceEmulation(ULONG op,HVDM hvdm,ULONG cb,PSZ psz)
{
  HHOOK hhook;

  AssertTRUE(op == VDHPROP_SET);
  SETBIT(pVDMData(hvdm)->flVDMXVideo,
         VDMX_RTRCEMULATE,
         (BOOL)psz);

  if (ALLOCHOOK((PFNARM)VVSpecialCaseIO,
                0,
                hhook,
                cb))
    ARMHOOK(hhook,
            hvdm);
  return 0;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetUpdateFrequency
 *
 * DESCRIPTION   = Set per-VDM graphics update frequency
 *
 *                 This routine is called when the user alters an existing
 *                 VDM's graphics update frequency "advanced property"
 *                 setting.
 *
 * INPUT         = op - operation to perform (set)
 *                 hvdm - target VDM
 *                 cb - length of value
 *                 psz - ptr to BOOL value
 *
 * OUTPUT        = returns 0 (no error)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

ULONG EXPENTRY VVSetUpdateFrequency(ULONG op,HVDM hvdm,ULONG cb,PSZ psz)
{
  AssertTRUE(op == VDHPROP_SET);
  pVDMData(hvdm)->nPeriodicLimit = ((ULONG)psz *100)/TIMER_CHECK;
  return 0;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetInt2F
 *
 * DESCRIPTION   = Set per-VDM INT 2Fh flag
 *
 *                 This routine is called when the user alters an existing
 *                 VDM's INT 2Fh setting.
 *
 * INPUT         = op - operation to perform (set)
 *                 hvdm - target VDM
 *                 cb - length of value
 *                 psz - ptr to BOOL value
 *
 *
 * OUTPUT        = returns 0 (no error)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

ULONG EXPENTRY VVSetInt2F(ULONG op,HVDM hvdm,ULONG cb,PSZ psz)
{
  AssertTRUE(op == VDHPROP_SET);
  SETBIT(pVDMData(hvdm)->flVDMXVideo,
         VDMX_INT2F,
         (BOOL)psz);

   #ifdef   VGA                                  /*                         */

  /*
  ** send INT 2F ON/OFF notification                                        
  */

  if ((pfnInt2FProc) &&                          /*                         */
  (flNotifyType&VDHVVD_NOTIFY_ON_OFF))           /*                         */
    (*pfnInt2FProc)(hvdm,
                    (ULONG)psz,
                    (PCRF)NULL);                 /*                         */
   #endif                                        /*                         */

#ifdef  GALE                                                        //J-TS0827
  pVDMData(hvdm)->GaleData.Int2FStack.flProcessing = FALSE;         //J-TS0830
  pVDMData(hvdm)->GaleData.Int2FStack.EventCnt     = 0;             //J-TS0830
  pVDMData(hvdm)->GaleData.Int2FStack.LastEvent    = NULL;          //J-TS0830
#endif  //GALE                                                      //J-TS0827

   return 0;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSetOnDemandAlloc
 *
 * DESCRIPTION   = Set per-VDM on-demand allocation flag
 *
 *                 This routine is called when the user alters an existing
 *                 VDM's on-demand allocation setting.
 *
 * INPUT         = op - operation to perform (set)
 *                 hvdm - target VDM
 *                 cb - length of value
 *                 psz - ptr to BOOL value
 *
 * OUTPUT        = returns 0 (no error)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

ULONG EXPENTRY VVSetOnDemandAlloc(ULONG op,HVDM hvdm,ULONG cb,PSZ psz)
{
  AssertTRUE(op == VDHPROP_SET);
  SETBIT(pVDMData(hvdm)->flVDMXVideo,
         VDMX_ONDEMAND,
         (BOOL)psz);
  return 0;
}

#endif                                           /* PROPERTIES              */

/***************************************************************************
 *
 * FUNCTION NAME = VVFgndContext()
 *
 * DESCRIPTION   = Finish foreground switch in VDM's context
 *
 *                  This is a context hook armed by VVSetFgnd and called in
 *                  the context of the new foreground VDM.  Its purpose is
 *                  to update the video memory mappings, and to initialize
 *                  the display via INT 10h if that has not been done yet.
 *
 * INPUT         = p    == undefined
 *                 pcrf -> VDM register frame (NULL if called from VDD)
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID HOOKENTRY VVFgndContext(PVOID p,PCRF pcrf)
{
  BYTE sav_PORT_VGADACREAD;                      /*                         */
  USHORT i;                                      /*                         */

  RequestMutexSem(VDMData.hmxVideoState);

  if (pcrf)
    VDMData.flVDMVideo &= ~VDM_FGNDHOOK;

  /*
  ** Check session state in case hook was postponed so long that
  ** we are once again background (which can happen with pop-ups).
  */

  if (VDMData.flVDMVideo&VDM_FGND)
  {

/*   #ifdef VGA                                                             */
/*    if (VDMData.flVDMXVideo & VDMX_SAVERESTORE) {                         */
/*   #endif                                                                 */

    /*
    ** If background hooks installed, remove
    */

    if (VDMData.flVDMVideo&VDM_BGNDREADY)
    {
      vvSetIOHooks(ahleBgnd,
                   FALSE,
                   TRUE);
      VDMData.flVDMVideo &= ~VDM_BGNDREADY;
    }

#ifdef SVGA
    /*
    ** Remove pixel transfer hooks on S3
    */
    if (ulSVGAAdapterType == S3_ADAPTER)
      v8514SetPixelIOHooks(FALSE);
#endif
    /*
    ** If foreground hooks not installed, install
    */

    if (!(VDMData.flVDMVideo&VDM_FGNDREADY))
    {
      vvSetIOHooks(ahleFgnd,
                   TRUE,
                   TRUE);
      VDMData.flVDMVideo |= VDM_FGNDREADY;
    }

    /*
    ** Disable fgnd and special I/O trapping where appropriate
    */

    vvEnableIO();

   #ifdef SVGA                                                  /*            */

    if (VDMData.flVDMXVideo & VDMX_ENHANCEDMODE)              /*            */
      vvMapBank(BANK0);
    else

   #endif                                                       /*            */

    /*
    ** Set up appropriate mappings
    */

#ifdef  VTEXT                                                           //J-TS00V
    if (VDMData.flVDMXVideo & VDMX_SAVERESTORE)                         //J-TS00V
#endif  //VTEXT                                                         //J-TS00V
    VVEnableBuffer(TRUE,
                   pcrf);

#ifndef  MONO             /* ** for primary adapter only **                 */
    if (pcrf)
      vvInt2FNotify(INT2F_SYSFGND,
                    pcrf);
#endif                                           /*                         */

    /*
    ** Force VDM to call INT 10h if it has no I/O state yet.
    */

    if (!(VDMData.flVDMVideo&(VDM_IOINIT|VDM_MODECHANGING)))
    {
      vvInt10Initialize(pcrf);

#ifdef   VGA                                     /*                         */

      /*
      ** Update virtual dac registers with physical regs              
      ** TO INSURE AN ACCURATE SHADOW IN INSTANCE DATA                
      */

      if (!(VDMData.flVDMVideo&VDM_WINDOWED))
      {                                          /*                         */
        sav_PORT_VGADACREAD = INB(PORT_VGADACREAD);/*                       */
        OUTB(PORT_VGADACREAD,
             0);                                 /*                         */

        for (i = 0; i < MAX_DACREGS; i++)
        {                                        /*                         */
          VDMData.adacDACData[i].dac_bRed        /*                         */
             = INB(PORT_VGADACDATA);             /*                         */
          VDMData.adacDACData[i].dac_bGreen      /*                         */
             = INB(PORT_VGADACDATA);             /*                         */
          VDMData.adacDACData[i].dac_bBlue       /*                         */
             = INB(PORT_VGADACDATA);             /*                         */
        }                                        /*                         */
        OUTB(PORT_VGADACREAD,
             sav_PORT_VGADACREAD);               /*                         */
      }                                          /*                         */
#endif                                           /*                         */
    }                                            /*                         */
#ifdef  XVIO                                                            //J-TS00V
    else if (VDMData.flVDMGale)                                         //J-TS00V
      vxAddEvent(VDMData.hvdmVideo,                                     //J-TS00V
                 VXEVENT_FOREGROUND, NULL, 0);                          //J-TS00V
#endif  //XVIO                                                          //J-TS00V
#ifdef  VTEXT                                                           //J-TS00V
    if (VDMData.GaleData.flVtext & VDMV_VTEXT_INSTALLED)                //J-TS00V
      vvFgndContextVtext(pcrf);                                         //J-TS00V
#endif  //VTEXT                                                         //J-TS00V

#ifdef   SVGA

      if (vdhBTR(&VDMData.flVDMVideo,
                 LOG2(VDM_FROZEN)))
      VDHThawVDM(CURRENT_VDM);

      vvUnLockSVGARegisters();                   /*                         */
#endif

/*   #ifdef VGA                                                             */
/*    } else {  ** send INT 2F notification for adapter owner **            */
/*      if (pcrf)                                                           */
/*          vvInt2FNotify(INT2F_SYSFGND, pcrf);                             */
/*    }                                                                     */
/*   #endif                                                                 */

  }
  ReleaseMutexSem(VDMData.hmxVideoState);
}

/***************************************************************************
 *
 * FUNCTION NAME = VVBgndContext()
 *
 * DESCRIPTION   = Finish background switch in VDM's context
 *
 *                 This is a context hook armed by VVSetBgnd and called in
 *                 the context of the new background VDM.  Its purpose is to
 *                 shrink the video buffers down to a reasonable size, and
 *                 update the video memory mappings.
 *
 * INPUT         = p    == undefined
 *                 pcrf -> VDM register frame (NULL if called from VDD)
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID HOOKENTRY VVBgndContext(PVOID p,PCRF pcrf)
{
  RequestMutexSem(VDMData.hmxVideoState);

  if (pcrf)
    VDMData.flVDMVideo &= ~VDM_BGNDHOOK;

  /*
  ** Check session state in case hook was postponed so long that
  ** we are once again foreground (which can happen with pop-ups).
  */

  /*           
  ** If another device registered for 2F notification, setup the hooks and
  ** issue the 2F. Otherwise, either issue the 2F or setup the hooks depending
  ** on the 2FPENDING flag. If 2FPENDING is set, FGND flag is still set.
  */
  if (!(VDMData.flVDMVideo&VDM_FGND))
  {

/*   #ifdef VGA                                                             */
/*    if (VDMData.flVDMXVideo & VDMX_SAVERESTORE) {                         */
/*   #endif                                                                 */

    /*
    ** If foreground hooks installed, remove
    */

    if (VDMData.flVDMVideo&VDM_FGNDREADY)
    {
      vvSetIOHooks(ahleFgnd,
                   FALSE,
                   TRUE);
      VDMData.flVDMVideo &= ~VDM_FGNDREADY;
    }

    /*
    ** If background hooks not installed, install
    */

    if (!(VDMData.flVDMVideo&VDM_BGNDREADY))
    {
      vvSetIOHooks(ahleBgnd,
                   TRUE,
                   TRUE);
      VDMData.flVDMVideo |= VDM_BGNDREADY;
    }

#ifdef SVGA
    /*
    ** Install pixel transfer hooks on S3. If no IOTRAPPING set, install
    ** the hooks for other IO ports. Once the VDM goes foreground, the
    ** ports will be disabled by the first trapped IO access.
    */
    if (ulSVGAAdapterType == S3_ADAPTER)                /*            */
    {
      v8514SetPixelIOHooks(TRUE);
      if(VDMData.flVDMXVideo & VDMX_NOIOTRAPPING)
        v8514SetIOHooks(TRUE);
    }
#endif
    /*
    ** Disable special VDM I/O trapping where appropriate
    */

    VVSpecialCaseIO(NULL,
                    NULL);

   #ifdef SVGA                                                  /*            */
    if (VDMData.flVDMXVideo & VDMX_ENHANCEDMODE)
    {
        vvUnMapBuffer();
        vvMapBank((*apfnSVGAGetBank[ulSVGAAdapterType])(CURRENT_VDM, TRUE));
    } else
   #endif                                                       /*            */

    {                                                           /*            */

    /*
    ** Shrink memory down (this could be done out-of-context
    ** now, but we might as well do it at the leisure of the VDM).
    */

    vvShrinkBuffer(CURRENT_VDM, FALSE);

   #ifdef SVGA
    /*
    ** If 2F caused created any mapping, invalidate it first
    */
    if (VDMData.flVDMXVideo & VDMX_INT2F)                       /*            */
       VVEnableBuffer(FALSE, pcrf);
   #endif

    /*
    ** Set up appropriate mappings
    */

#ifdef  VTEXT                                                           //J-TS00V
    if (VDMData.flVDMXVideo & VDMX_SAVERESTORE)                         //J-TS00V
#endif  //VTEXT                                                         //J-TS00V
    VVEnableBuffer(TRUE, pcrf);

    }                                                           /*            */
#ifndef  MONO             /* ** for primary adapter only **                 */

#ifdef SVGA                                                     /*            */
    if(VDMData.flVDMXVideo & VDMX_INT2FREGIST)
#endif
    if (pcrf)
      vvInt2FNotify(INT2F_SYSBGND,
                    pcrf);
#endif                                           /*                         */

    /*
    ** Force VDM to call INT 10h if we don't have state yet
    */

    if (!(VDMData.flVDMVideo&(VDM_IOINIT|VDM_MODECHANGING)))
      vvInt10Initialize(pcrf);

#ifdef  VTEXT                                                           //J-TS00V
    if (VDMData.GaleData.flVtext & VDMV_VTEXT_INSTALLED)                //J-TS00V
      vvBgndContextVtext(pcrf);                                         //J-TS00V
#endif  //VTEXT                                                         //J-TS00V


#ifdef   SVGA

    /*
    ** Freeze SVGA modes
    */

#ifdef  VTEXT
   if (!(VDMData.GaleData.flVtext & VDMV_SUPPORTED_TEXT_MODE))
#endif  //VTEXT
    if (!(VDMData.flVDMXVideo & VDMX_INT2F) &&
        (VDMData.flVDMXVideo & VDMX_ENHANCEDMODE) &&
        !VDMData.flBgndExecEnabled ||
        ((VDMData.ulBIOSMode & ~BIOSVINFO_DONTCLEAR) ==
          BIOSVMODE_CO320X200X256 &&
       !(VDMData.aregSEQData[REG_SEQMEMMODE] & SEQMEM_CHAIN4)))
    {
      if (!vdhBTS(&VDMData.flVDMVideo, LOG2(VDM_FROZEN)))
        VDHFreezeVDM(CURRENT_VDM);

      vvAddEvent(CURRENT_VDM,
                 VVDEVENT_MODE,
                 NULL,
                 0);
    }
#endif

  }
#ifdef SVGA
  else
    if (VDMData.flVDMXVideo & VDMX_INT2FPENDING && pcrf)       /*            */
      vvInt2FNotify(INT2F_SYSBGND,
                    pcrf);
#endif
  ReleaseMutexSem(VDMData.hmxVideoState);
}

/***************************************************************************
 *
 * FUNCTION NAME = vvFreezeVDM()
 *
 * DESCRIPTION   = Worker to freeze VDM/notify Shield
 *
 * INPUT         = hvdm  == VDM handle
 *                 fWait == TRUE to wait for thaw, FALSE to simply freeze and return
 *
 * OUTPUT        = TRUE if freeze succeeded, FALSE if error occurred (ie, VDM was killed)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

BOOL PRIVENTRY vvFreezeVDM(HVDM hvdm,BOOL fWait)
{
  register INT i;
  VDHSEMSTATE vss;
  BOOL fSuccess = TRUE;
  register PVDMDATA pvd = pVDMData(hvdm);

  /*
  ** Reset semaphore before forcing FROZEN bit on, to guarantee
  ** the WaitEventSem will not miss any posting done in vvThawVDM.
  */

  ResetEventSem(pvd->hevFreezeThaw);

  /*
  ** Test-and-set frozen state, to minimize nested freezing and
  ** redundant/confusing user notifications .
  */

  if (!vdhBTS(&pvd->flVDMVideo,
              LOG2(VDM_FROZEN)))
  {

    /*
    ** Freeze first
    */

    AssertRC(VDHFreezeVDM(hvdm));

    /*
    ** Post the event to the Shield
    */

    vvUpdateModeData(hvdm);

    /*
    ** If VDM is foreground, then we have a REAL problem
    */

    if (pvd->flVDMVideo&VDM_FGND)
      vvAddEvent(hvdm,
                 VVDEVENT_SWITCHERROR,
                 NULL,
                 0);
  }

  if (fWait)
  {

    /*
    ** Get # times we grabbed this semaphore
    */

    VDHQuerySem(pvd->hmxVideoState,
                SSToDS(&vss));

    for (i = 0; i < vss.vss_cRequest; i++)
      ReleaseMutexSem(pvd->hmxVideoState);

#ifdef  XVIO                                                            //J-TS00V
    vxFlushEvent(hvdm, VXEVENT_NONE, XEVENT_FORCE);                     //J-TS00V
#endif  //XVIO                                                          //J-TS00V

    fSuccess = WaitEventSem(pvd->hevFreezeThaw);

    /*
    ** Regrab this semaphore the appropriate number of times
    */

    while (i--)
      RequestMutexSem(pvd->hmxVideoState);
  }
  return  fSuccess;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvThawVDM()
 *
 * DESCRIPTION   = Worker to thaw VDM/notify Shield
 *
 * INPUT         = hvdm == VDM handle
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID PRIVENTRY vvThawVDM(HVDM hvdm)
{
  register PVDMDATA pvd = pVDMData(hvdm);


  if (vdhBTR(&pvd->flVDMVideo,
             LOG2(VDM_FROZEN)))
  {

    /*
    ** Post the event to the Shield
    */

    vvUpdateModeData(hvdm);

    /*
    ** Thaw last
    */

    VDHThawVDM(hvdm);

    /*
    ** In case there's anyone blocked in vvFreezeVDM, wake them up
    */

    PostEventSem(pvd->hevFreezeThaw);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = vvInt2FNotify()
 *
 * DESCRIPTION   = Worker to issue INT 2Fh to VDM
 *
 * INPUT         = ulFunc == INT 2Fh code
 *                 pcrf   -> VDM register frame
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID PRIVENTRY vvInt2FNotify(ULONG ulFunc,register PCRF pcrf)
{

#ifndef  MONO                 /* any primary device except MONO             */

#ifdef  VTEXT                                                           //J-TS00V
 if (!(VDMData.flVDMVideo & VDM_FGND) ||                                //J-TS00V
     !(VDMData.GaleData.flVtext & VDMV_SUPPORTED_TEXT_MODE))            //J-TS00V
#endif  //VTEXT                                                         //J-TS00V
  if (VDMData.flVDMXVideo&VDMX_INT2F)
  {                                              /*                         */

#ifdef  GALE                                                        //J-TS0827
    if (VDMData.GaleData.Int2FStack.flProcessing) {                 //J-TS0827
      if (!VDMData.GaleData.Int2FStack.EventCnt) {                  //J-TS0827
        if (VDMData.GaleData.Int2FStack.LastEvent == ulFunc)        //J-TS0827
          VDMData.GaleData.Int2FStack.EventCnt = 2;                 //J-TS0827
        else                                                        //J-TS0827
          VDMData.GaleData.Int2FStack.EventCnt = 1;                 //J-TS0827
      } else {                                                      //J-TS0827
        if (VDMData.GaleData.Int2FStack.LastEvent == ulFunc)        //J-TS0827
          VDMData.GaleData.Int2FStack.EventCnt = 2;                 //J-TS0827
        else                                                        //J-TS0827
          VDMData.GaleData.Int2FStack.EventCnt = 1;                 //J-TS0827
      }                                                             //J-TS0827
      return;                                                       //J-TS0827
    } else {                                                        //J-TS0827
      if (VDMData.GaleData.Int2FStack.LastEvent == ulFunc) {        //J-TS0827
        ulFunc = (ulFunc == INT2F_SYSFGND) ? INT2F_SYSBGND :        //J-TS0827
                                             INT2F_SYSFGND;         //J-TS0827
        VDMData.GaleData.Int2FStack.EventCnt = 1;                   //J-TS0827
      }                                                             //J-TS0827
    }                                                               //J-TS0827
                                                                    //J-TS0827
    VDMData.GaleData.Int2FStack.LastEvent    = ulFunc;              //J-TS0827
    VDMData.GaleData.Int2FStack.flProcessing = TRUE;                //J-TS0827
#endif  //GALE                                                      //J-TS0827

    #ifdef   VGA                                  /*                         */

    /*
    ** send start of INT 2F notification                                    
    */

    if ((pfnInt2FProc) &&                        /*                         */
       (flNotifyType&VDHVVD_NOTIFY_START))       /*                         */
      (*pfnInt2FProc)(VDMData.hvdmVideo,         /*                         */
                      (VDMData.flVDMVideo&VDM_FGND)?/*                      */
                         VDHVVD_INT2F_FG_START:  /*                         */
                         VDHVVD_INT2F_BG_START,  /*                         */
                      pcrf);                     /*                         */
    #endif                                        /*                         */
    VDHPushRegs(VDHREG_AX);
    AX(pcrf) = ulFunc;

    if (VDMData.flV86mode = ((flVdmStatus&VDM_STATUS_VPM_APP) && !(flVdmStatus
       &VDM_STATUS_VPM_EXEC)))
    {                                            /*                         */
      VDHSwitchToVPM();                          /*                         */
    }                                            /*                         */
#ifdef V21YEE07
     /*            
     **  Fix removed because it requires MR1 kernel.  This way
     **  video drivers based on the DDK will run on both GA and MR1.
     */
    if (flVdmStatus&VDM_STATUS_VPM_EXEC)         /*                  73541  */
    {                                            /*                  73541  */
       if (em86Is32Sel(SS(pcrf)))                /* is stack big?    73541  */
       {                                         /*                  73541  */
          VDHBeginUseVPMStack();                 /* switch stacks    73541  */
          flBigSel = TRUE;                       /*                  73541  */
       }                                         /*                  73541  */
    }                                            /*                  73541  */
#endif
    VDHArmReturnHook(VDMData.hhookInt2FReturn,
                     VDHARH_RECURSIVE_CSEIP_HOOK);
    VDHPushInt(INT2F_INT);
  }
#endif                                           /*                         */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvInt2FReturn()
 *
 * DESCRIPTION   = Return hook for our INT 2Fh calls
 *
 * INPUT         = pvoid == undefined
 *                 pcrf  -> VDM register frame
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID HOOKENTRY vvInt2FReturn(PVOID p,register PCRF pcrf)
{

#ifdef   VGA                                     /*                         */

  /*
  ** send end of INT 2F notification                                        
  */

  if ((pfnInt2FProc) &&                          /*                         */
     (flNotifyType&VDHVVD_NOTIFY_END))           /*                         */
    (*pfnInt2FProc)(VDMData.hvdmVideo,           /*                         */
                    (VDMData.flVDMVideo&VDM_FGND)?/*                        */
                       VDHVVD_INT2F_FG_END:      /*                         */
                       VDHVVD_INT2F_BG_END,      /*                         */
                    pcrf);                       /*                         */
#endif                                           /*                         */

#ifndef  MONO                 /* any primary device except MONO             */

#ifdef V21YEE07
     /*            
     **  Fix removed because it requires MR1 kernel.  This way
     **  video drivers based on the DDK will run on both GA and MR1.
     */
  if (flBigSel)                                  /* is stack big?    73541  */
  {                                              /*                  73541  */
     flBigSel = FALSE;                           /*                  73541  */
     VDHEndUseVPMStack();                        /* restore stack    73541  */
  }                                              /*                  73541  */
#endif

  if (VDMData.flV86mode)
  {                                              /*                         */
    VDHSwitchToV86();                            /*                         */
  }                                              /*                         */
  VDHPopRegs(VDHREG_AX);
#endif                                           /*                         */
#ifdef SVGA
  VDHPostEventSem(VDMData.hevInt2FDelaySwitch);                 /*          */
#endif

#ifdef  GALE                                                        //J-TS0827
  VDMData.GaleData.Int2FStack.flProcessing = FALSE;                 //J-TS0827
  if (VDMData.GaleData.Int2FStack.EventCnt) {                       //J-TS0827
    VDMData.GaleData.Int2FStack.EventCnt--;                         //J-TS0827
    if (VDMData.GaleData.Int2FStack.LastEvent == INT2F_SYSFGND)     //J-TS0827
      vvInt2FNotify(INT2F_SYSBGND, pcrf);                           //J-TS0827
    else                                                            //J-TS0827
      vvInt2FNotify(INT2F_SYSFGND, pcrf);                           //J-TS0827
  }                                                                 //J-TS0827
#endif  //GALE                                                      //J-TS0827
}

#ifdef   VGA                                     /*                         */

/***************************************************************************
 *
 * FUNCTION NAME = VDHRegisterInt2FProc
 *
 * DESCRIPTION   = INT 2F registration routine
 *
 *                  This routine is called by whichever another primary
 *                  virtual video device driver such as 8514 or XGA requires
 *                  completion of INT 2F notification.
 *
 * INPUT         = flType  =  type of notification required (see VVD.H)
 *                 pfn     -> VVD entry point to signal INT 2F completion
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID VDHENTRY VDHRegisterInt2FProc(FLAGS flType,PFNINT2FP pfn)/*            */
{                                                /*                         */

  /*
  ** FLAG: need to handle multiple device registerations                    
  */

  flNotifyType = flType;                         /* save notification type
                                                                            */
  pfnInt2FProc = pfn;                            /* save routine address
                                                                            */
}                                                /*                         */
#endif                                           /*                         */
#ifdef   SVGA                                    /*                         */
/***************************************************************************
 *
 * FUNCTION NAME = vvSVGASetBgnd
 *
 * DESCRIPTION   =  SVGA background processing
 *
 *                  This routine is called by vvSetBgnd to take appropriate
 *                  action depending on the video switch property. If set, it
 *                  will delay session switch until INT 2F completes so that
 *                  full foreground video access is given to the VDM.
 *                  This function assumes that mutex sem to instance is
 *                  already acquired and will not release it at the end.
 *                  It also assumes that instance is marked BGND already.
 *
 * INPUT         = hvdm == VDM handle
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/
VOID PRIVENTRY vvSVGASetBgnd(HVDM hvdm)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  BOOL f2FStatus;                                /*                         */

  /*
  ** If 2F property exists, we need to delay the session switch
  ** until 2F handler finishes, so that it has full access to
  ** the hardware. When 2F completes, we mark instance as BGND
  ** and setup another appointment to install all the hooks and
  ** perform the mappings in the BgndContext.
  ** If the property is not set, we freeze the modes that can't
  ** be virtualized at this point.
  */

  if (!(pvd->flVDMXVideo & VDMX_INT2F) ||
      ((pfnInt2FProc != NULL) && (pvd->flVDMXVideo & VDMX_INT2F)))
  {

    /*
    ** In another device registered for 2F notification with us, don't
    ** block the switch thread as they may be doing the same, but
    ** setup all the IO hooks and perform the mapping as well as
    ** issue the Int 2F. Don't freeze the VDM for the same reason.
    */
    if((pfnInt2FProc != NULL) && (pvd->flVDMXVideo & VDMX_INT2F))
    {
      pvd->flVDMXVideo |= VDMX_INT2FREGIST;
      pvd->flVDMXVideo &= ~VDMX_INT2FPENDING;
      pvd->flVDMVideo  |= VDM_FGND;                                  /*            */
    }
  }
  else if (pvd->flVDMVideo & VDM_IOINIT)                              /*            */
  {
    /*
    ** Mark the instance as pending and foreground
    ** so that BgndContext knows not to install
    ** the hooks and just call the Int2FNotify routine.
    ** This is not done on instance creation.
    */
    pvd->flVDMXVideo |= VDMX_INT2FPENDING;
    pvd->flVDMVideo  |= VDM_FGND;                                     /*            */
    f2FStatus = TRUE;
    pvd->flVDMVideo &= ~VDM_FROZEN;
    /*
    ** On accelerated adapters, VDM has to be allowed to run until
    ** all engine pending commands are satisfied before switching it into
    ** the backgroud. This is enforced thru block/release of the shell
    ** thread on hev8514Busy semaphore. VDM's access to the accelerator
    ** ports release this semaphore, but block the VDM itself. VDM then must
    ** be allowed to run so that 2F notification is received.
    */
    if(ulSVGAAdapterType == S3_ADAPTER)
      v8514UnlockIO(hvdm);
    ReleaseMutexSem(pvd->hmxVideoState);
    /*
    ** Make sure we thaw the instance completelly.
    */
    while (VDHIsVDMFrozen(hvdm))
      VDHThawVDM(hvdm);

    /*
    ** Make sure VDM is not blocked as idle.
    ** Block on the 2F semaphore until either timeout occurs or
    ** 2F successfuly returns.
    */
    VDHWakeIdle(hvdm);                                                /*          */
    VDHResetEventSem(pvd->hevInt2FDelaySwitch);                       /*          */
    if(!VDHWaitEventSem(pvd->hevInt2FDelaySwitch,MAX_VDM_WAIT))
       f2FStatus = FALSE;
    RequestMutexSem(pvd->hmxVideoState);
    VDHFreezeVDM(hvdm);
    pvd->flVDMVideo &= ~VDM_FGND;                                     /*            */
    pvd->flVDMXVideo &= ~VDMX_INT2FPENDING;
    /*
    ** Instance already marked BGND by the first context.
    ** Setup another appointment for BgndContext to do
    ** all the bacground preparations.
    */
    if (!vdhBTS(&pvd->flVDMVideo,
                LOG2(VDM_BGNDHOOK))){
      VDHWakeIdle(hvdm);                                              /*            */
      VDHArmContextHook(pvd->hhookBgndContext,
                        hvdm);
    }
  }
}
#endif
#pragma  END_SWAP_CODE

