/*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 = VVDEVRQ.C
 *
 * DESCRIPTIVE NAME = Virtual Video Device Request Processing
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's VDHRequestVDD support.
 *
 *
 * FUNCTIONS    VVDevReqProc()             VDHRequestVDD router
 *              vvDevPostPeek()            Process peek events for windowed VDMs
 *              vvDevPostRead()            Process read events for windowed VDMs
 *              vvKeyboardCheck()          Check for video events due to keyboard
 *                                         activity
 *              vvDevPostPaste()           Process paste events for windowed VDMs
 *              vvDevPostMouse()           Perform video updates according to
 *                                         mouse event
 *              vvDevAcceptAdapter()       Accept adapter ownership for this VDM
 *              vvDevReleaseAdapter()      Release adapter ownership for this VDM
 *              vvDevAcceptDisplay()       Accept display ownership for this VDM
 *              vvDevReleaseDisplay()      Release display ownership for this VDM
 *              vvDevPostVideoEvent()      Post a video event to the Shield
 *              VVInitContext()            Disable and/or reinitialize all VRAM pages
 *              vvDevSaveRestoreAdapter()  Enable or disable save/restore of the
 *                                         VGA's video state
 *              vvDevRepaint()             Enable or disable PM repaint
 *              vvDevRequestController()   Request video controller access for VDD
 *              vvDevFreeController()      Release video controller access for VDD
 *              vvDevWindowsDeskTop()      Make a windowed VDM Seamless
 *              vvDevEnableDDE()           Set or Clear DDE flag
 *              vvDevXGAPresent()          Know VXGA installed
 *              vvDevUnmapVRAM()           Unmap VRAM since VXGA will map
 *
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


#include <mvdm.h>
#include <vvd.h>
#include "vvdp.h"

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif
#define  INCL_DOSERRORS
#include <bseerr.h>

extern ULONG flVVD;                              /*                         */

#pragma  BEGIN_SWAP_DATA

extern HVDD hvddMouse;                                          /*          */
extern PDEVFUN apfnDevReq[];
extern LSENTRY lseHeadActive;
extern HMXSEM hmxWindowedEvent;
extern HEVSEM hevWindowedEvent;
extern ULONG nWindowedEvents;                                   /*          */
extern ULONG nWindowedVDMs;                                     /*          */

#ifdef   VGA
extern BOOL flXGAPresent;                                       /*          */
extern BOOL flDualDisplayConf;                                  /*          */
#endif

#pragma  END_SWAP_DATA
#pragma  BEGIN_SWAP_CODE


/***************************************************************************
 *
 * FUNCTION NAME = VVDevReqProc()
 *
 * DESCRIPTION   = VDHRequestVDD router
 *
 *                 This subroutine is registered during VDD initialization
 *                 via VDHRegisterVDD, and receives requests from other VDDs
 *                 that have have registered under the same name and use
 *                 VDHRequestVDD.  See VVD.H for a description of the
 *                 input/output buffers, if any.
 *
 * INPUT         = hvdm    -> VDM
 *                 ulFunc  == function code
 *                 pbufIn  -> input buffer (not used here)
 *                 pbufOut -> output buffer (not used here)
 *
 * OUTPUT        = SUCCESS
 *                     True
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 based on function code
 *                   route to appropriate worker function
 *
 ****************************************************************************/

LONG EXPENTRY VVDevReqProc(HVDM hvdm,ULONG ulFunc,PVOID pIn,PVOID pOut)
{

  if (ulFunc > VVDDEVREQ_MAX)
  {
    VDHSetError(ERROR_INVALID_FUNCTION);
    return  FALSE;
  }

  else

    return (apfnDevReq[--ulFunc])(hvdm,
                                  (BOOL)pIn);
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevPostPeek()
 *
 * DESCRIPTION   = Process peek events for windowed VDMs
 *
 *                 This subroutine processes the VVDDEVREQ_POSTPEEK request.
 *                 This is used for windowed VDMs to help select a good time
 *                 to check for window updates, as well as adjust window
 *                 origin.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == TRUE if data exists to peek, FALSE if not (CURRENTLY NOT USED)
 *
 * OUTPUT        = SUCCESS
 *                     True
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevPostPeek(HVDM hvdm,BOOL fData)
{

  if (++pVDMData(hvdm)->nPeeks > PEEKS_CHECK)
    vvKeyboardCheck(hvdm,
                    FALSE);
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevPostRead()
 *
 * DESCRIPTION   = Process read events for windowed VDMs
 *
 *                 This subroutine processes the VVDDEVREQ_POSTREAD request.
 *                 This is used for windowed VDMs to *suggest* that the VDM
 *                 has finished video updates for the moment, and that this
 *                 may be a good time to refresh the window.  Some number of
 *                 PEEKs means the same thing.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == TRUE if data exists to read, FALSE if not (CURRENTLY NOT USED)
 *
 * OUTPUT        = SUCCESS
 *                     True
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevPostRead(HVDM hvdm,BOOL fData)
{
  vvKeyboardCheck(hvdm,
                  TRUE);
  pVDMData(hvdm)->nPeeks = PEEKS_CHECK-1;
  pVDMData(hvdm)->flVDMVideo |= VDM_KEYREAD;
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvKeyboardCheck()
 *
 * DESCRIPTION   = Check for video events due to keyboard activity
 *
 * INPUT         = hvdm  -> VDM
 *                 fRead == TRUE if key is being read, FALSE if not
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvKeyboardCheck(HVDM hvdm,BOOL fRead)
{
  BOOL fPeriodic;
  register PVDMDATA pvd = pVDMData(hvdm);

  RequestMutexSem(hmxWindowedEvent);
  pvd->nPeeks = 0;

  /*
  ** See if any new video events should be posted
  */

  fPeriodic = PERIODIC_KBDPEEK;

  if (fRead || pvd->flVDMVideo&VDM_KEYREAD)
  {
    fPeriodic = PERIODIC_KBDREAD;
    pvd->flVDMVideo &= ~(VDM_KEYREAD|VDM_INPUTPOSTED);
  }

  if (!VVCheckForEvents(hvdm,
                        fPeriodic))
    PostEventSem(hevWindowedEvent);
  vvAddEvent(hvdm,
             VVDEVENT_INPUT,
             &pvd->vvCursor,
             EVENT_OWNER);
  ReleaseMutexSem(hmxWindowedEvent);
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevPostPaste()
 *
 * DESCRIPTION   = Process paste events for windowed VDMs
 *
 *                 This subroutine processes the VVDDEVREQ_POSTPASTE
 *                 request.  This is used for windowed VDMs to notify the
 *                 Shield that it can paste more data to the VDM, if any
 *                 remains.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = SUCCESS
 *                     True
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevPostPaste(HVDM hvdm,BOOL fData)
{

  if (fData)
  {
    vvAddEvent(hvdm,
               VVDEVENT_PASTE,
               NULL,
               0);
    pVDMData(hvdm)->flVDMVideo |= VDM_KEYPASTED;
  }

  else
  {
    vvAddEvent(hvdm,
               VVDEVENT_ENDPASTE,
               NULL,
               0);
    pVDMData(hvdm)->flVDMVideo &= ~VDM_KEYPASTED;
  }
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevPostMouse()
 *
 * DESCRIPTION   = Perform video updates according to mouse event
 *
 *                 This subroutine processes the VVDDEVREQ_POSTMOUSE
 *                 request.  This hvdm -> VDM h is used for windowed VDMs to
 *                 check for changes very soon after an fData == undefined
 *                 initial mouse button down (or up) event has been posted
 *                 here.  SUCCESS True FAILURE False (error code set via
 *                 VDHSetError)
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = SUCCESS
 *                     True
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevPostMouse(HVDM hvdm,BOOL fData)
{
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevAcceptAdapter()
 *
 * DESCRIPTION   = Accept adapter ownership for this VDM
 *
 *
 *                 This subroutine processes the VVDDEVREQ_DEVACCEPT
 *                 request, allowing another video VDD to step out of the
 *                 way and return to adapter control to us.  Note that we
 *                 cannot assume our previous page table information is
 *                 still correct, so we reinitialize the adapter via INT
 *                 10h (hopefully no one inside the VDM has trampled our
 *                 INT 10h set-mode hook).
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = SUCCESS
 *                     True (ownership accepted)
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevAcceptAdapter(HVDM hvdm,BOOL fData)
{
  register PVDMDATA pvd = pVDMData(hvdm);


  if (!vdhBTS(&pvd->flVDMXVideo,
              LOG2(VDMX_DEVOWNER)))
  {
    *(PBOOL)VDHQueryHookData(pvd->hhookInitContext) = TRUE;

    if (!vdhBTS(&pvd->flVDMXVideo,
                LOG2(VDMX_INITHOOK)))
      VDHArmContextHook(pvd->hhookInitContext,
                        hvdm);
  }
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevReleaseAdapter()
 *
 * DESCRIPTION   = Release adapter ownership for this VDM
 *
 *                 This subroutine processes the VVDDEVREQ_DEVRELEASE
 *                 request, allowing another video VDD to step in and take
 *                 control of this device.  It is the caller's
 *                 responsibility to insure that the VDM is under restraint
 *                 (eg, frozen) during this time of transition.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = SUCCESS
 *                     True (ownership released)
 *                 FAILURE
 *                     VDDREQ_PASS (not owning VDD)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevReleaseAdapter(HVDM hvdm,BOOL fData)
{
  register PVDMDATA pvd = pVDMData(hvdm);


  if (vdhBTR(&pvd->flVDMXVideo,
             LOG2(VDMX_DEVOWNER)))
  {
    *(PBOOL)VDHQueryHookData(pvd->hhookInitContext) = FALSE;

    if (!vdhBTS(&pvd->flVDMXVideo,
                LOG2(VDMX_INITHOOK)))
      VDHArmContextHook(pvd->hhookInitContext,
                        hvdm);
    return  TRUE;
  }
  return  VDDREQ_PASS;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevAcceptDisplay()
 *
 * DESCRIPTION   = Accept display ownership for this VDM
 *
 *                 This subroutine processes the VVDDEVREQ_DSPACCEPT request.
 *                 Any non-originating VDD receiving this request must
 *                 acknowledge if it is now capable of owning the display,
 *                 taking responsibility not for its hardware for rather for
 *                 pointer-drawing or anything else to be defined as part of
 *                 the "display focus".
 *
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = SUCCESS
 *                     True (ownership accepted)
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevAcceptDisplay(HVDM hvdm,BOOL fData)
{
  pVDMData(hvdm)->flVDMXVideo |= VDMX_DSPOWNER;
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevReleaseDisplay()
 *
 * DESCRIPTION   = Release display ownership for this VDM
 *
 *                 This subroutine processes the VVDDEVREQ_DSPRELEASE
 *                 request.  Any non-originating VDD receiving this request
 *                 must acknowledge if it currently owns the display,
 *                 relinquishing responsibility not for its hardware for
 *                 rather for pointer-drawing or anything else to be defined
 *                 as part of the "display focus".
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = SUCCESS
 *                     True (ownership released)
 *                 FAILURE
 *                     VDDREQ_PASS (VDD issued call itself)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevReleaseDisplay(HVDM hvdm,BOOL fData)
{
  pVDMData(hvdm)->flVDMXVideo &= ~VDMX_DSPOWNER;
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevPostVideoEvent()
 *
 * DESCRIPTION   = Post a video event to the Shield
 *
 *                 This subroutine processes the VVDDEVREQ_POSTEVENT
 *                 request.
 *
 * INPUT         = hvdm -> VDM
 *                 pvvp -> event data
 *
 * OUTPUT        = SUCCESS
 *                     True
 *                 FAILURE
 *                     False (error code set via VDHSetError)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevPostVideoEvent(HVDM hvdm,register PVVPOST pvvp)
{
  register PVDMDATA pvd = pVDMData(hvdm);                       /*            */
  VMSSIZE vmssNew;                                              /*            */
  PVVMODE pvvMode;                                              /*            */

  if (pvvp->vvp_flEvent&POSTEVENT_ADD)
  {
    vvAddEvent(hvdm,
               pvvp->vvp_iEvent,
               pvvp->vvp_pEvent,
               pvvp->vvp_flEvent);

    /*
    **            - And notify the virtual mouse driver
    */

    if ((pvvp->vvp_iEvent == VVDEVENT_MODE) &&
        (pvvMode = (PVVMODE)pvvp->vvp_pEvent))
    {
      vmssNew.vmss_nb = sizeof(VMSSIZE);
      vmssNew.vmss_lMode = -1;
      vmssNew.vmss_ulWidth = pvvMode->vvm_nCols * pvvMode->vvm_ulCellWidth;
      vmssNew.vmss_ulHeight = pvvMode->vvm_nRows * pvvMode->vvm_ulCellHeight;
      vmssNew.vmss_ulCellWidth = pvvMode->vvm_ulCellWidth;
      vmssNew.vmss_ulCellHeight = pvvMode->vvm_ulCellHeight;

      if ( hvddMouse &&
          (pvd->flVDMVideo & VDM_STATEINIT) )
          VDHRequestVDD(hvddMouse,
                        hvdm,
                        VMDEVREQ_SETSIZE,
                        SSToDS(&vmssNew),
                        NULL);
    }

  }
  else

    if (pvvp->vvp_flEvent&POSTEVENT_FLUSH)

      vvFlushEvent(hvdm,
                   pvvp->vvp_iEvent,
                   pvvp->vvp_flEvent);

    else

      if (pvvp->vvp_flEvent&POSTEVENT_DELETE)

        vvDeleteEvent(hvdm,
                      pvvp->vvp_iEvent,
                      pvvp->vvp_flEvent);

#ifdef   VDDSTRICT

  else
    Assert(FALSE);
#endif
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVInitContext()
 *
 * DESCRIPTION   = Disable and/or reinitialize all VRAM pages
 *
 * INPUT         = pfEnable -> TRUE to enable, FALSE to disable
 *                 pcrf     -> VDM register frame
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID HOOKENTRY VVInitContext(register PBOOL pfEnable,PCRF pcrf)
{
  VDMData.flVDMXVideo &= ~VDMX_INITHOOK;

  if (*pfEnable)
  {
    VDMData.flVDMVideo &= ~(VDM_IOINIT|VDM_MODECHANGING);

    if (VDMData.flVDMVideo&VDM_FGND)
      VVFgndContext(NULL,
                    NULL);

    else
      VVBgndContext(NULL,
                    NULL);
  }

  else
  {
    vvSetFaultHooks(FALSE,
                    TRUE);

    if (VDMData.flVDMVideo&VDM_FGNDREADY)
    {
      vvSetIOHooks( FALSE,              /* Fgnd */              /*          */
                    FALSE,              /* Remove */
                    TRUE );             /* Wait */
      VDMData.flVDMVideo &= ~VDM_FGNDREADY;
    }

    if (VDMData.flVDMVideo&VDM_BGNDREADY)
    {
      vvSetIOHooks( TRUE,               /* Bgnd */              /*          */
                    FALSE,              /* Remove */
                    TRUE );             /* Wait */
      VDMData.flVDMVideo &= ~VDM_BGNDREADY;
    }
    VVEnableBuffer(FALSE,
                   pcrf);
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevSaveRestoreAdapter()
 *
 * DESCRIPTION   = Enable or disable save/restore of the VGA's video state
 *
 *                 This subroutine processes the VVDDEVREQ_SAVERESTORE
 *                 request.  An internal flag will be set/clear based on
 *                 whether SAVE/RESTORE of the VGA is required by the
 *                 calling VDD.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = True
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevSaveRestoreAdapter(HVDM hvdm,BOOL fData)
{

  if (fData)
  {

    /*
    ** indicate Save/Restore of VGA video state is required
    */

    pVDMData(hvdm)->flVDMXVideo |= VDMX_SAVERESTORE;
  }

  else
  {

    /*
    ** indicate Save/Restore of VGA video state is not required
    */

    pVDMData(hvdm)->flVDMXVideo &= ~VDMX_SAVERESTORE;
  }
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevRepaint()
 *
 * DESCRIPTION   = Enable or disable PM repaint
 *
 *                 This subroutine processes the VVDDEVREQ_REPAINT request.
 *                 A global flag will be set/clear based on whether VRAM
 *                 will be dirty by the DOS application which may required
 *                 a complete PM repaint.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData == undefined
 *
 * OUTPUT        = True
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevRepaint(HVDM hvdm,BOOL fData)
{

  if (fData)
  {

    /*
    ** don't reset the VRAMISTOAST bit (force repaint)
    */

    flVVD |= VVD_REPAINT+VVD_VRAMISTOAST;
  }

  else
  {

    /*
    ** always reset the VRAMISTOAST bit (no repaint necessary
    */

    flVVD &= ~VVD_REPAINT;
  }
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevRequestController()
 *
 * DESCRIPTION   = Request video controller access for VDD
 *
 *                 This subroutine processes the VVDDEVREQ_REQCTRL
 *                 function.  It is issued by a cooperating VDD on behalf
 *                 of a VDM Video Driver if it finds the VGA controller is
 *                 owned by another VDM.
 *
 * INPUT         = hvdm  -> VDM
 *                 fData is not used
 *
 * OUTPUT        = SUCCESS
 *                     Zero
 *                 FAILURE
 *                     Error code (none)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevRequestController(HVDM hvdm,BOOL fData)
{

#ifdef   VGA
  vvRequestController(DISPLAY_OWNER,
                      FALSE);
#endif
  return  NO_ERROR;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevFreeController()
 *
 * DESCRIPTION   = Release video controller access for VDD
 *
 *                 This subroutine processes the VVDDEVREQ_FREECTRL
 *                 function.  Note that it is only issued if the VDD has set
 *                 the shared NOTIFY flag;
 *
 * INPUT         = hvdm  -> VDM
 *                 fData is not used
 *
 * OUTPUT        = SUCCESS
 *                     Zero
 *                 FAILURE
 *                     Error code (none)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevFreeController(HVDM hvdm,BOOL fData)
{

#ifdef   VGA
  vvFreeController(DISPLAY_OWNER);
#endif
  return  NO_ERROR;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevWindowsDeskTop()
 *
 * DESCRIPTION   = Make a windowed VDM Seamless
 *
 *                 This subroutine processes the VVDDEVREQ_PM_WINDOWS
 *                 function, either enable/disable IOPL privilege and access
 *                 to A0000h.
 *
 * INPUT         = hvdm -> VDM
 *                 fSet == TRUE to make a windowed VDM SEAMLESS, FALSE to release
 *
 * OUTPUT        =
 *                 SUCCESS
 *                     Zero
 *                 FAILURE
 *                     Error code (ie, invalid parameter, etc)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevWindowsDeskTop(HVDM hvdm,BOOL fSet)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  LONG rc = ERROR_NOT_READY;

#ifdef   VGA                                     /*                         */

  /*
  ** fail request if the target VDM is not windowed
  */

  if (pvd->flVDMVideo&VDM_WINDOWED)
  {

    /*
    ** no-op if current state matches function being requested
    */

    if (fSet)
    {

      /*
      ** SET request
      */

      if (pvd->flVDMXVideo&VDMX_SEAMLESS)        /* already Seamless?       */
        return  NO_ERROR;                        /* no-op request           */

#ifdef SVGA                                                     /*          */
      vvAcceleratorSetIOHooks( FALSE );                         /*          */
      vvAcceleratorSetBgndOnlyHooks( FALSE );                   /*          */
#endif /* SVGA */
      /*
      ** remove all I/O hooks
      */

      if( vvSetIOHooks( TRUE,           /* Bgnd */              /*          */
                        FALSE,          /* Remove */
                        FALSE ) )       /* NO Wait */
      {

        /*
        ** Disable all current VRAM mapping
        */

        VVEnableBuffer(FALSE,
                       NULL);

        /*
        ** Map linear A0000h (128K) to physical                       
        */

        pvd->vdhmt.vdhmt_laddr = pvd->vdhms.vdhms_laddr = (ULONG)0x0A0000;
        pvd->vdhmt.vdhmt_hmap = pvd->vdhms.vdhms_hobj = 0L;
        pvd->vdhmt.vdhmt_cpg = 0x20;             /*                         */

        if (VDHMapPages(&pvd->vdhms,
                        &pvd->vdhmt,
                        VDHMT_PHYSICAL))
        {
          pvd->flVDMXVideo |= VDMX_SEAMLESS;
          RequestMutexSem(hmxWindowedEvent);

          /*
          ** Remove all pending events
          */

          while (pvd->flEventsPending)
          {
            pvd->flEventsPending &= ~(1 << vdhBSF(pvd->flEventsPending));
            nWindowedEvents--;
          }

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

          REMOVEENTRY( pvd->hvdmVideo,  /* uses lseHeadActive */
                       Active );
          nWindowedVDMs--;
          ReleaseMutexSem(hmxWindowedEvent);
          rc = NO_ERROR;
        }

        else

          /*
          ** Reset all I/O Hooks
          */

          vvSetIOHooks( TRUE,           /* Bgnd */              /*          */
                        TRUE,           /* Install */
                        TRUE );         /* Wait */
      }
    }

    else
    {

      /*
      ** CLEAR request
      */

      if (!(pvd->flVDMXVideo&VDMX_SEAMLESS))     /* not Seamless?           */
        return  NO_ERROR;                        /* no-op request           */

      /*
      ** intall background hooks
      */

      if( vvSetIOHooks( TRUE,           /* Bgnd */              /*          */
                        TRUE,           /* Install */
                        TRUE ) )        /* Wait */
      {

        /*
        ** Map linear A0000h to INVALID
        */

        pvd->vdhms.vdhms_hobj = 0;

        if (VDHMapPages(&pvd->vdhms,
                        &pvd->vdhmt,
                        VDHMT_INVALID))
        {
          pvd->flVDMXVideo &= ~VDMX_SEAMLESS;

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

          RequestMutexSem(hmxWindowedEvent);
          ADDENTRY( pvd->hvdmVideo,     /* uses lseHeadActive */
                    Active );
          nWindowedVDMs++;
          ReleaseMutexSem(hmxWindowedEvent);
          rc = NO_ERROR;
        }
      }
    }
  }
#endif                                           /*                         */
return  rc;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevEnableDDE()
 *
 * DESCRIPTION   = Set or Clear DDE flag
 *
 * INPUT         = hvdm  -> VDM
 *                 fSet  == TRUE if to SET, FALSE if not
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvDevEnableDDE(HVDM hvdm,BOOL fSet)/*                        */
{                                                /*                         */
  register PVDMDATA pvd = pVDMData(hvdm);        /*                         
                                                                            */

  RequestMutexSem(hmxWindowedEvent);             /*                         */

  if (!(pvd->flVDMVideo&VDM_DYING))
  {                                              /*                         */
    pvd->fDDEflag = (USHORT)fSet;                /*                         */
    vvAddEvent(hvdm,
               VVDEVENT_DDE,
               &pvd->fDDEflag,
               0);                               /*                         */
  }                                              /*                         */
  ReleaseMutexSem(hmxWindowedEvent);             /*                         */
}                                                /*                         */

/***************************************************************************
 *
 * FUNCTION NAME = vvDevXGAPresent()                                        
 *
 * DESCRIPTION   = Be aware of VXGA's presence
 *
 * INPUT         = hvdm  -> VDM
 *                 fSet  == TRUE if called by VXGA
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvDevXGAPresent(HVDM hvdm,BOOL fSet)
{
#ifdef VGA
  flXGAPresent |= fSet;                                         /*          */
#endif
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDev8514Present()                                        
 *
 * DESCRIPTION   = Be aware of V8514's presence
 *
 * INPUT         = hvdm  -> VDM
 *                 fSet  == TRUE if called by V8514
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvDev8514Present(HVDM hvdm,BOOL fSet)
{
#ifdef   VGA

  /*
  **           
  ** If dual display configuration, 8514 is the owner of its
  ** own display, so don't mark the flag.
  */
  if (fSet && !flDualDisplayConf)
     flVVD |= VVD_8514PRESENT;                          /*            */

#endif /* VGA */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvDevUnmapVRAM()                                          
 *
 * DESCRIPTION   = Unmap VRAM VXGA wants to map it
 *
 * INPUT         = hvdm  -> VDM
 *                 fSet  == TRUE to unmap VRAM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

LONG PRIVENTRY vvDevUnmapVRAM(HVDM hvdm,BOOL fSet)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  LONG rc = 0;

#ifdef   VGA

  if (fSet)
  {
     /*
     ** Disable all current VRAM mapping
     */

     VVEnableBuffer(FALSE,
                    NULL);

     rc = 1;                                     /* all done; go back ok    */
  }
#endif
}
#pragma  END_SWAP_CODE

