/*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 = VVACCEL.C
 *
 * DESCRIPTIVE NAME = Virtual Video Accelerated SVGA Specific Processing
 *
 *
 * VERSION = V2.1
 *
 * DATE      04/30/93
 *
 * DESCRIPTION  This module contains all accelerator specific SVGA code and data.
 *
 *
 * FUNCTIONS
 *      vvAcceleratorLockIO()           Prevent VDM from doing further I/O
 *      vvAcceleratorUnlockIO()         Allow VDM I/O to proceed
 *      vvAcceleratorEnterIO()          Verify that VDM is allowed to do I/O
 *      vvAcceleratorExitIO()           Mark VDM I/O completed
 *      vvAcceleratorInstallWordHooks()
 *      vvAcceleratorSetWordHookState()
 *      vvAcceleratorRead()
 *      vvAcceleratorWrite()
 *      vvAcceleratorFindWRegReadPort()
 *      vvAcceleratorFindWRegWritePort()
 *
 *      vvAcceleratorChip()             Return TRUE if adapter is an accelerator
 *      vvAcceleratorIsEnhancing()      Return TRUE if accelerator enhances mode type
 *      vvAcceleratorSetBgndOnlyHooks() Install/remove background only I/O hooks
 *      vvAcceleratorInstallIOHooks()   Install I/O hooks
 *      vvAcceleratorSetIOHooks()       Install/remove I/O hooks
 *      vvAcceleratorUpdateModeData()   Redetermine current screen state
 *      vvAcceleratorWaitOnEngine()     Wait until current accelerator operation finished
 *      vvAcceleratorUpdateIOState()    Transfer hardware state to virtual I/O
 *      vvAcceleratorRestoreIOState()   Transfer virtual I/O state to hardware
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


#define  IO8BIT           /* CL386 Version 6.00.054 FLAG:              */
#include <mvdm.h>
#include <vvd.h>
#include <vvdp.h>

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

/*
**     Externals
*/
extern SA8514INFO sA8514Info;                                   /*          */
extern PSSVGAINFO psCurAdapterInfo;                             /*          */
extern PSACCELERATORINFO psCurAcceleratorInfo;                  /*          */

/*
** Currently the set of accelerator object classes includes:
**
** sAcceleratorInfo
**   sA8514Info (the default accelerator)
**     sATIAcceleratorInfo
**     sS3AcceleratorInfo
**   sWDC31Info
**   sTsengW32Info
**
** Indentation shows sub classing
*/
#pragma  BEGIN_SWAP_DATA
PVDM  pvdmStartupMMIOActive = 0;                                            /*            */
ULONG npgStartupMMIOActive = 0;                                             /*            */
#pragma  END_SWAP_DATA
#pragma  BEGIN_SWAP_CODE
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegLowShadowUpdate
 *
 * DESCRIPTION   = Update byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get word read
 *
 * OUTPUT        = Copys data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegLowShadowUpdate(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  BYTEOF( *(PWORD)(psTrapRegInfo->pvTrapReadShadow), 0 ) =
    *(PBYTE)pSource;
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegLowShadowRead
 *
 * DESCRIPTION   = Read byte of trap word register from shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegLowShadowRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  *(PBYTE)pTarget =
    BYTEOF( *(PWORD)(psTrapRegInfo->pvTrapReadShadow), 0 );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegLowShadowWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/
                                                                /*          */
VOID    PRIVENTRY vvTrapWRegLowShadowWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  BYTEOF( *(PWORD)(psTrapRegInfo->pvTrapWriteShadow), 0 ) =
    *(PBYTE)pSource;
}

                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegLowRealRead
 *
 * DESCRIPTION   = Read byte of trap word register from port
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegLowRealRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  *(PBYTE)pTarget =
    INB( psTrapRegInfo->portTrap );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegLowRealWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegLowRealWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  OUTB( psTrapRegInfo->portTrap,
        *(PBYTE)pSource );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegLowUnhook
 *
 * DESCRIPTION   = Unhook low byte of trap word register
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorEnterIO
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegLowUnhook(
  PSTRAPREGINFO psTrapRegInfo )
{
  VDHSetIOHookState( CURRENT_VDM,
                     psTrapRegInfo->portTrap, /* & ~0x0001 */
                     1,
                     &psTrapRegInfo->piohTrap [0],
                     FALSE );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegHighShadowUpdate
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get word read
 *
 * OUTPUT        = Copys data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegHighShadowUpdate(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  BYTEOF( *(PWORD)(psTrapRegInfo->pvTrapReadShadow), 1 ) =
    *(PBYTE)pSource;
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegHighShadowRead
 *
 * DESCRIPTION   = Read byte of trap word register from shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegHighShadowRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  *(PBYTE)pTarget =
    BYTEOF( *(PWORD)(psTrapRegInfo->pvTrapReadShadow), 1 );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegHighShadowWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegHighShadowWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  BYTEOF( *(PWORD)(psTrapRegInfo->pvTrapWriteShadow), 1 ) =
    *(PBYTE)pSource;
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegHighRealRead
 *
 * DESCRIPTION   = Read byte of trap word register from port
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegHighRealRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  *(PBYTE)pTarget =
    INB( psTrapRegInfo->portTrap | 0x0001 );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegHighRealWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegHighRealWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  OUTB( psTrapRegInfo->portTrap | 0x0001,
        *(PBYTE)pSource );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegHighUnhook
 *
 * DESCRIPTION   = Unhook high byte of trap word register
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorEnterIO
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegHighUnhook(
  PSTRAPREGINFO psTrapRegInfo )
{
  VDHSetIOHookState( CURRENT_VDM,
                     psTrapRegInfo->portTrap | 0x0001,
                     1,
                     &psTrapRegInfo->piohTrap [1],
                     FALSE );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegWholeShadowUpdate
 *
 * DESCRIPTION   = Update byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get word read
 *
 * OUTPUT        = Copys data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegWholeShadowUpdate(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  *(PWORD)(psTrapRegInfo->pvTrapReadShadow) =
    *(PWORD)pSource;
}

                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegWholeShadowRead
 *
 * DESCRIPTION   = Read byte of trap word register from shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegWholeShadowRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  *(PWORD)pTarget =
    *(PWORD)(psTrapRegInfo->pvTrapReadShadow);
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegWholeShadowWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegWholeShadowWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  *(PWORD)(psTrapRegInfo->pvTrapWriteShadow) =
     *(PWORD)pSource;
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegWholeRealRead
 *
 * DESCRIPTION   = Read byte of trap word register from port
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegWholeRealRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  PORT port;
  WORD wData;

  port = psTrapRegInfo->portTrap;
  _asm
  {
    mov  dx, word ptr port
    in   ax, dx
    mov  wData, ax
  };
  *(PWORD)pTarget = wData;
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegWholeRealWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegWholeRealWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  PORT port;
  WORD wData;

  wData = *(PWORD)pSource;
  port = psTrapRegInfo->portTrap;
  _asm
  {
    mov  dx, word ptr port
    mov  ax, wData
    out  dx, ax
  }
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapWRegWholeUnhook
 *
 * DESCRIPTION   = Unhook whole trap word register
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorEnterIO
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapWRegWholeUnhook(
  PSTRAPREGINFO psTrapRegInfo )
{
  vvTrapWRegLowUnhook( psTrapRegInfo );
  vvTrapWRegHighUnhook( psTrapRegInfo );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapBRegWholeShadowUpdate
 *
 * DESCRIPTION   = Update byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get word read
 *
 * OUTPUT        = Copys data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapBRegWholeShadowUpdate(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  register PBYTE pbShadowAddr;                                  /*          */

  pbShadowAddr =                                                /*          */
    (PBYTE) psTrapRegInfo->pvTrapReadShadow;                    /*          */
  if( psTrapRegInfo->fTrapType & READ_INDX_FLAG)                /*          */
    pbShadowAddr +=                                             /*          */
      *(PBYTE)((PPLE) psTrapRegInfo)->ppleBRegIndx->            /*          */
                sTrapBRegInfo.pvTrapWriteShadow;                /*          */
  *pbShadowAddr = *(PBYTE)pSource;
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapBRegWholeShadowRead
 *
 * DESCRIPTION   = Read byte of trap word register from shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapBRegWholeShadowRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  register PBYTE pbShadowAddr;                                  /*          */

  pbShadowAddr =                                                /*          */
    (PBYTE) psTrapRegInfo->pvTrapReadShadow;                    /*          */
  if( psTrapRegInfo->fTrapType & READ_INDX_FLAG)                /*          */
    pbShadowAddr +=                                             /*          */
      *(PBYTE)((PPLE) psTrapRegInfo)->ppleBRegIndx->            /*          */
                sTrapBRegInfo.pvTrapWriteShadow;                /*          */
  *(PBYTE)pTarget = *pbShadowAddr;                              /*          */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapBRegWholeShadowWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapBRegWholeShadowWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  register PBYTE pbShadowAddr;                                  /*          */

  pbShadowAddr =                                                /*          */
    (PBYTE) psTrapRegInfo->pvTrapWriteShadow;                   /*          */
  if( psTrapRegInfo->fTrapType & READ_INDX_FLAG)                /*          */
    pbShadowAddr +=                                             /*          */
      *(PBYTE)((PPLE) psTrapRegInfo)->ppleBRegIndx->            /*          */
                sTrapBRegInfo.pvTrapWriteShadow;                /*          */
  *pbShadowAddr = *(PBYTE)pSource;                              /*          */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapBRegWholeRealRead
 *
 * DESCRIPTION   = Read byte of trap word register from port
 *
 *                 This subroutine is called whenever a VDM
 *                 reads a byte from half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pTarget -> target to store byte read
 *
 * OUTPUT        = Returns data from shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapBRegWholeRealRead(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pTarget )
{
  *(PBYTE)pTarget =
    INB( ((PSCGAINFO) psCurAdapterInfo)->                       /*          */
           pportfnCGAAdjustedPort( psTrapRegInfo ) );           /*          */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapBRegWholeRealWrite
 *
 * DESCRIPTION   = Write byte of trap word register to shadow
 *
 *                 This subroutine is called whenever a VDM
 *                 writes a byte to half of an accelerator word register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapBRegWholeRealWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PVOID pSource )
{
  OUTB( ((PSCGAINFO) psCurAdapterInfo)->                        /*          */
          pportfnCGAAdjustedPort( psTrapRegInfo ),              /*          */
        *(PBYTE)pSource );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvTrapBRegWholeUnhook
 *
 * DESCRIPTION   = Unhook low byte of trap word register
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 pSource -> source to get byte written
 *
 * OUTPUT        = Returns data to shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorEnterIO
 *
 ***********************************************************************/

VOID    PRIVENTRY vvTrapBRegWholeUnhook(
  PSTRAPREGINFO psTrapRegInfo )
{
  VDHSetIOHookState( CURRENT_VDM,
                     ((PSCGAINFO) psCurAdapterInfo)->           /*          */
                       pportfnCGAAdjustedPort(                  /*          */
                         psTrapRegInfo ),        /* & ~0x0001 *//*          */
                     1,
                     psTrapRegInfo->piohTrap,
                     FALSE );
}

#pragma  END_SWAP_CODE

#pragma  BEGIN_SWAP_DATA
                                                                /*          */
STRAPREGPARTINFO sTrapWRegLow =
{
  &vvTrapWRegLowShadowUpdate,
  &vvTrapWRegLowShadowRead,
  &vvTrapWRegLowShadowWrite,
  &vvTrapWRegLowRealRead,
  &vvTrapWRegLowRealWrite,
  &vvTrapWRegLowUnhook,
};

STRAPREGPARTINFO sTrapWRegHigh =
{
  &vvTrapWRegHighShadowUpdate,
  &vvTrapWRegHighShadowRead,
  &vvTrapWRegHighShadowWrite,
  &vvTrapWRegHighRealRead,
  &vvTrapWRegHighRealWrite,
  &vvTrapWRegHighUnhook,
};

STRAPREGPARTINFO sTrapWRegWhole =
{
  &vvTrapWRegWholeShadowUpdate,
  &vvTrapWRegWholeShadowRead,
  &vvTrapWRegWholeShadowWrite,
  &vvTrapWRegWholeRealRead,
  &vvTrapWRegWholeRealWrite,
  &vvTrapWRegWholeUnhook,
};
                                                                /*          */
STRAPREGPARTINFO sTrapBRegWhole =                               /*          */
{                                                               /*          */
  &vvTrapBRegWholeShadowUpdate,                                 /*          */
  &vvTrapBRegWholeShadowRead,                                   /*          */
  &vvTrapBRegWholeShadowWrite,                                  /*          */
  &vvTrapBRegWholeRealRead,                                     /*          */
  &vvTrapBRegWholeRealWrite,                                    /*          */
  &vvTrapBRegWholeUnhook,                                       /*          */
};                                                              /*          */
#pragma  END_SWAP_DATA                                          /*          */


#pragma  BEGIN_SWAP_CODE
/* Was v8514LockIO */                                           /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorLockIO()
 *
 * DESCRIPTION   = Prevent VDM from doing further accelerator I/O.
 *                 This function is different from A8514 one in the sense that
 *                 it doesn't freeze or block the VDM
 *                 if the IOOWNED bit was already set.
 *                 It instead just sets the bit, so that next port hook's
 *                 EnterIO function can block the VDM.
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = I/O inhibited
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead (when waiting for not busy and now not)
 *      vvAcceleratorWrite (when waiting for not busy and now cmd)
 *      vvAcceleratorInstallIOHooks (before installing)
 *      VVSetBgnd (when VDM_DYING)
 *
 ***********************************************************************/

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

  /*
  ** Claim the IOOWNED bit, this VDM should now not do accelerator I/O.
  */
  vdhBTS( &pvd->flVDMX2Video,
          LOG2( VDMX2_8514IOOWNED ) );
}
/* Was v8514UnlockIO */                                         /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorUnlockIO()
 *
 * DESCRIPTION   = Allow VDM I/O to proceed
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = I/O may proceed
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVSetFgnd (when VDMX_SAVERESTORE)
 *      vvSVGASetBgnd
 *
 ***********************************************************************/

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

  /*
  ** Release the IOOWNED bit, mark it unblocked.
  ** The VDM may now do accelerator I/O.
  */
  /*!!Shouldn't we use vdhBTR? */
  pvd->flVDMX2Video &= ~VDMX2_8514IOOWNED;
  /* Never true unless this is an accelerator chip: */
  if( pvd->flVDMX2Video & VDMX2_8514IOWAKEME )
    /* Don't use this semaphore unless this is an accelerator chip: */
    PostEventSem( pvd->VdmSVGA.hev8514WakeUp );
  vdhBTR( &pvd->flVDMX2Video,
          LOG2( VDMX2_8514BLOCKED ) );
}
/* Was v8514EnterIO */                                          /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorEnterIO()
 *
 * DESCRIPTION   = Verify that VDM is allowed to do I/O
 *
 * INPUT         = port == port being accessed
 *                 size == size of port being accessed (1 or 2)
 * OUTPUT        =
 *                 I/O may proceed
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *      vvAcceleratorWrite
 *
 ***********************************************************************/

BOOL    PRIVENTRY vvAcceleratorEnterIO(
  PSTRAPREGINFO psTrapRegInfo,
  PSTRAPREGPARTINFO psTrapRegPartInfo )
{
  /* Lock accelerater I/O and while already locked by some other thread: */
  while( vdhBTS( &VDMData.flVDMX2Video,
                 LOG2( VDMX2_8514IOOWNED ) ) )
  {
    ResetEventSem( VDMData.VdmSVGA.hev8514WakeUp );
    /*
    ** BLOCKED causes vvAcceleratorUpdateModeData (if called)
    ** to suspend for unsupported mode.
    ** Gets unBLOCKED later by VVSetFgnd
    */
    VDMData.flVDMX2Video |= (VDMX2_8514IOWAKEME | VDMX2_8514BLOCKED);

    /*
    ** Now that we've armed the WAKEUP semaphore and set the WAKEME
    ** bit, make sure IOOWNED still set;  if it isn't, then we may have
    ** missed the chance to be awakened, not to mention the fact that it
    ** may be moot now anyway
    */

    if( VDMData.flVDMX2Video & VDMX2_8514IOOWNED )
    {
      /*
      ** This will convey to the Shield that the VDM is suspended
      */
      vvUpdateModeData( CURRENT_VDM );
      if( !WaitEventSem( VDMData.VdmSVGA.hev8514WakeUp ) )
        return( FALSE ); /* FLAG: -- assume we got ERROR_INTERRUPT  */
                         /*          due to DosKillProcess by Shell */
    }
    VDMData.flVDMX2Video &= ~VDMX2_8514IOWAKEME;
  }
  /* In case we never WaitEventSem for WakeUp! */
  vdhBTR( &VDMData.flVDMX2Video,
          LOG2( VDMX2_8514BLOCKED ) );
  /* Now this thread is the sole owner of the accelerator! */
  /*
  ** Check to see if we should disable trapping after first access now
  */
  if( (VDMData.flVDMVideo & VDM_FGND)
      && (VDMData.flVDMXVideo & VDMX_NOIOTRAPPING)
      /* Don't unhook while waiting to change sessions! */      /*          */
      && !(VDMData.flVDMX2Video & VDMX2_8514ENGBUSY)            /*          */
//                && !psCurAcceleratorInfo->
//                     pbfnAcceleratorStaysHooked( psTrapRegInfo ) )
    && !(psTrapRegInfo->fTrapType & PORT_STAYS_HOOKED)) /*            */
    psTrapRegPartInfo->pfnTrapUnhook( psTrapRegInfo );
  return( TRUE );
}
/* Was v8514ExitIO */                                           /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAccleratorExitIO()
 *
 * DESCRIPTION   = Mark VDM I/O completed
 *
 * INPUT         = None
 *
 * OUTPUT        = I/O completed
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *      vvAcceleratorWrite
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorExitIO( VOID )
{
  /*!! Note this is just the similar to UnlockIO except for fixed hvdm */
  /*!! Shouldn't we use vdhBTR? */
  VDMData.flVDMX2Video &= ~VDMX2_8514IOOWNED;
  if( VDMData.flVDMX2Video & VDMX2_8514IOWAKEME )
    PostEventSem( VDMData.VdmSVGA.hev8514WakeUp );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorInstallWordHooks()
 *
 * DESCRIPTION   = Install one set of word I/O hooks
 *                 and set the initial state to trapped.
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvA8514InstallIoHooks
 *      vvWDInstallIoHooks
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorInstallWordHooks(
  PORT port )
{
  PSTRAPREGINFO psTrapRegInfo;

  psTrapRegInfo =
    &psCurAcceleratorInfo->
      psAcceleratorTrapRegInfo
        [psCurAcceleratorInfo->
          puifnAcceleratorPortIndex( port )];
  /* port may not equal portTrap field */                       /*          */
  /* if it is a multiply mapped register */                     /*          */
  AssertRC( VDHInstallIOHook( CURRENT_VDM,
                              port /* & ~0x0001 */,             /*          */
                              1,
                              &psTrapRegInfo->piohTrap [0],
                              VDHIIH_NO_SIMULATE ) );
  AssertRC( VDHInstallIOHook( CURRENT_VDM,
                              port | 0x0001,                    /*          */
                              1,
                              &psTrapRegInfo->piohTrap [1],
                              NULL ) );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorSetWordHookState()
 *
 * DESCRIPTION   = Install/remove word I/O hooks
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvA8514SetBgndOnlyHooks
 *      vvA8514SetIoHooks
 *      vvWDSetBgndOnlyHooks
 *      vvWDSetIoHooks
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorSetWordHookState(
  PORT port,
  FLAGS fl )
{
  PSTRAPREGINFO psTrapRegInfo;

  psTrapRegInfo =
    &psCurAcceleratorInfo->
      psAcceleratorTrapRegInfo
        [psCurAcceleratorInfo->
          puifnAcceleratorPortIndex( port )];
  /* port may not equal portTrap field */                       /*          */
  /* if it is a multiply mapped register */                     /*          */
  VDHSetIOHookState( CURRENT_VDM,
                     port /* & ~0x0001 */,                      /*          */
                     1,
                     &psTrapRegInfo->piohTrap [0],
                     fl );
  VDHSetIOHookState( CURRENT_VDM,
                     port | 0x0001,                             /*          */
                     1,
                     &psTrapRegInfo->piohTrap [1],
                     fl );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorRead()
 *
 * DESCRIPTION   = Read accelerator register
 *
 *                 This subroutine is called whenever a VDM
 *                 reads from an accelerator register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 psTrapRegPartInfo -> functions for trap reg
 *                 pTarget -> target to store read
 *
 * OUTPUT        = Returns data from port or shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvA8514ReadWRegByteL
 *      vvA8514ReadWRegByteH
 *      vvA8514ReadMFRegByteL
 *      vvA8514ReadMFRegByteH
 *      vvWDReadWRegByteL
 *      vvWDReadWRegByteH
 *      vvWDReadIndxByteL
 *      vvWDReadIndxByteH
 *      vvWDReadDataByteL
 *      vvWDReadDataByteH
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorRead(
  PSTRAPREGINFO psTrapRegInfo,
  PSTRAPREGPARTINFO psTrapRegPartInfo,
  PVOID pTarget )
{
  /*
  ** Now get shadow the data
  */
  psTrapRegPartInfo->pfnTrapShadowRead( psTrapRegInfo,
                                        pTarget );
  if( VDMData.flVDMVideo & VDM_FGND )
  {
    if( (VDMData.flVDMX2Video & VDMX2_8514ENGBUSY)
        && !psCurAcceleratorInfo->
              pbfnAcceleratorBusy( CURRENT_VDM ) )              /*          */
    {
      /*
      ** VDM is being switched into the background while an
      ** accelerator operation was in the progress. The assumption is
      ** that application will not be programming the accelerator unless
      ** the engine busy flag is reset. So, read access to the status
      ** register is trapped and as soon as the engine busy is reset,
      ** VDM is blocked from doing further IO, as not to have a chance
      ** to program the accelerator again. The shell switching thread is
      ** released by posting the event semaphore.
      */
      PostEventSem( VDMData.VdmSVGA.hev8514Busy );
      vvAcceleratorLockIO( CURRENT_VDM );
    }
    if( vvAcceleratorEnterIO( psTrapRegInfo,
                              psTrapRegPartInfo ) )
    {
      psTrapRegPartInfo->pfnTrapRealRead( psTrapRegInfo,
                                          pTarget );
      /*
      ** Now shadow the data before ExitIO and NOT after,
      ** to keep the shadow in sync with the SVGA hardware
      ** when there are multiple threads accessing SVGA hardware.
      */
      psTrapRegPartInfo->pfnTrapShadowUpdate( psTrapRegInfo,
                                              pTarget );
      vvAcceleratorExitIO();
    }
    /* else semaphore error, don't bother doing anything! */
  }
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorWrite()
 *
 * DESCRIPTION   = Write accelerator register
 *
 *                 This registered subroutine is called whenever a VDM
 *                 writes to an accelerator register.
 *
 * INPUT         = psTrapRegInfo -> info about trap reg
 *                 psTrapRegPartInfo -> functions for trap reg
 *                 pSource -> source data for write
 *
 * OUTPUT        = Writes data to port or shadow
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvA8514WriteWRegByteL
 *      vvA8514WriteWRegByteH
 *      vvA8514WriteMFRegByteL
 *      vvA8514WriteMFRegByteH
 *      vvWDWriteWRegByteL
 *      vvWDWriteWRegByteH
 *      vvWDWriteIndxByteL
 *      vvWDWriteIndxByteH
 *      vvWDWriteDataByteL
 *      vvWDWriteDataByteH
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorWrite(
  PSTRAPREGINFO psTrapRegInfo,
  PSTRAPREGPARTINFO psTrapRegPartInfo,
  PVOID pSource,
  BOOL bIsCmd)
{
  /*
  ** Allow some minimal kinds of background access
  */
  if( !(VDMData.flVDMVideo & VDM_FGND)
      && (!bIsCmd
          || (VDMData.flVDMXVideo & VDMX_INT2F)) )
    /* Can shadow anything which does NOT */
    /* start the engine or change bits in other regs */
    psTrapRegPartInfo->pfnTrapShadowWrite( psTrapRegInfo,
                                           pSource );
  else
  {
    if( bIsCmd
        && (VDMData.flVDMX2Video & VDMX2_8514ENGBUSY) )
    {
      /*
      ** VDM is being switched into the background while an
      ** accelerator operation was in the progress. The application is
      ** programming the engine again without checking the busy status,
      ** possibly because its previous command did not require its involvement.
      ** VDM is blocked from doing further IO, as not to have a chance
      ** to program the accelerator again. The shell switching thread is
      ** released by posting the event semaphore.
      */
      PostEventSem(VDMData.VdmSVGA.hev8514Busy);
      vvAcceleratorLockIO( CURRENT_VDM );
    }
    if( vvAcceleratorEnterIO( psTrapRegInfo,
                              psTrapRegPartInfo ) )
    {
      psTrapRegPartInfo->pfnTrapRealWrite( psTrapRegInfo,
                                           pSource );
      /*
      ** Now shadow the data before ExitIO and NOT after,
      ** to keep the shadow in sync with the SVGA hardware
      ** when there are multiple threads accessing SVGA hardware.
      */
      psTrapRegPartInfo->pfnTrapShadowWrite( psTrapRegInfo,
                                             pSource );
      /*!! We set & clear this, but no one looks! */
      VDMData.flVDMX2Video |= VDMX2_8514IOINIT;
      vvAcceleratorExitIO();
    }
    /* else semaphore error, don't bother doing anything! */
  }
}
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorChip()                  /          
 *
 * DESCRIPTION   = Returns TRUE if the chip is an accelerator.
 *
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorIsEnhancing
 *
 ***********************************************************************/
BOOL    PRIVENTRY vvAcceleratorChip( VOID )     /*            */
{
  return( (psCurAcceleratorInfo) &&
          (psCurAcceleratorInfo->pbfnAcceleratorChip) &&
          psCurAcceleratorInfo->pbfnAcceleratorChip());
}
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorInstallIOHooks()
 *
 * DESCRIPTION   = Install I/O hooks and set the initial state to trapped.
 *                 All writable registers which are either unreadable,
 *                 write once, or commands should be trapped.
 *                 All readable registers should be read in by
 *                 vvAcceleratorUpdateIOState (preferred) or trapped.
 *                 All trapped or read registers restored by
 *                 vvAcceleratorRestoreIOState.
 *
 *                 This routine installs all the appropriate I/O
 *                 handlers for the current VDM.
 *
 *                 Install all I/O handlers.
 *                 This will enable IO trapping for all ports.
 *                 If there is NOIOTRAPPING in foreground,
 *                 trapping will be disabled on the first trapped port access.
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVCreate
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorInstallIOHooks(
  HVDM hvdm )
{
  if( vvAcceleratorChip() )             /*            */
  {
    /*
    ** Lock accelerator I/O for now, until...
    */
    vvAcceleratorLockIO( hvdm );
    psCurAcceleratorInfo->pfnAcceleratorInstallIoHooks();       /*          */
  }
}
/* Was v8514SetPixelIOHooks() */                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorSetBgndOnlyHooks()
 *
 * DESCRIPTION   = Install/remove I/O hooks
 *
 *                 This routine installs all the appropriate I/O
 *                 handlers for the current VDM which trap in background only.
 *                 Usually this is only for performance reasons,
 *                 or because these are write once registers!
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = fl = TRUE for on, FALSE for off
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvDevWindowsDeskTop (FALSE)
 *      VVFgndContext (FALSE)
 *      VVBgndContext (TRUE)
 *
 ***********************************************************************/
VOID    PRIVENTRY vvAcceleratorSetBgndOnlyHooks(
  FLAGS fl )
{
  if( vvAcceleratorChip() )                     /*            */
    psCurAcceleratorInfo->pfnAcceleratorSetBgndOnlyHooks( fl ); /*          */
}
/* Was v8514SetIOHooks() */                                     /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorSetIOHooks()
 *
 * DESCRIPTION   = Set/reset I/O hooks
 *
 *                 This routine installs all the appropriate I/O
 *                 handlers for the current VDM which trap
 *                 in both foreground and background.
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvDevWindowsDeskTop (FALSE)
 *      VVBgndContext (TRUE)
 *      VVUpdateContext (TRUE)
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorSetIOHooks(
  FLAGS fl )
{
  if( vvAcceleratorChip() )             /*            */
    psCurAcceleratorInfo->pfnAcceleratorSetIoHooks( fl );       /*          */
}
/* Was vv8514ReturnLineLength */                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorUpdateScreenState()
 *
 * DESCRIPTION   = Adjust dimension data for accelerated modes,
 *                 depending on the memory map organization.
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvUpdateScreenState
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorUpdateScreenState(
  HVDM hvdm )
{
  if (vvAcceleratorChip())              /*            */
    psCurAcceleratorInfo->pfnAcceleratorUpdateScrnState( hvdm );/*          */
}
/* Was v8514WaitOnEngine */                                     /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorWaitOnEngine()
 *
 * DESCRIPTION   = If accelerator enabled, wait until all pending commands
 *                 have completed. VDM assumed unfrozen.
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        =
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVSetBgnd
 *
 * PSEUDO CODE
 *  if (Engine Busy)
 *    Mark VDM instance as WAIT_ON_ENGINE
 *    if accelerator ports not trapped
 *      Set IO hooks
 *    endif
 *    ResetEventSemaphore (VdmSVGA.hevEngineBusy)
 *    while (EngineBusy and TotalTimeout < MAX))
 *      WaitEventSemaphore (hevEngineBusy, TimeOut)
 *      Add TimeOut to TotalTimeout
 *    endwhile
 *    if EngineBusy
 *      Reset Engine
 *    endif
 *    Mark VDM instance as not WAIT_ON_ENGINE
 *  endif
 *
 ***********************************************************************/

VOID    PRIVENTRY vvAcceleratorWaitOnEngine(
  HVDM hvdm,
  BOOL flFrozenOnEntry )                                        /*          */
{
  register PVDMDATA pvd = pVDMData(hvdm);
  WORD wData;                                                   /*          */
  ULONG ulTimeOut = 0;
  BOOL bPrevUnlock;                                             /*          */

  if( vvAcceleratorChip() &&                    /*            */
      psCurAcceleratorInfo->pbfnAcceleratorIsOn( hvdm ) ) /*            */
  {
    /*
    ** Busy flag should be reset when engine has completed all the pending
    ** commands. However, on some chip revisions, due to the linear
    ** addressing being enabled, FIFO status will not be empty.
    ** Our code should never be checking for the FIFO status instead of busy.
    ** The VDM will be given a chance to continue running for a while and
    ** clear the engine.
    ** This thread blocks on a semaphore, which gets released by VDM
    ** either accessing the status port and finding the engine not busy,
    ** or attempting to program the command register.
    ** As there is a chance that VDM will not be doing any of the port access,
    ** once the block times out, engine is checked again and then blocked.
    ** If VDM has accessed the command port and released our semaphore and
    ** the engine is still found busy, that means that an operation which
    ** is not dependant on the app's involvment is in progress,
    ** so VDM will be blocked and we will keep checking the busy flag.
    ** If the time-out accumulated and the engine has not cleared yet,
    ** the state would be assumed beyond help and the engine will be reset.
    */

    /* Must freeze other thread to have clear access to regs */ /*          */
    /* Otherwise lock/unlock/index to busy may not work right *//*          */
    bPrevUnlock = vvSVGALockPushState( hvdm );                  /*          */
    while( (ulTimeOut < MAX_VDM_WAIT)
           && psCurAcceleratorInfo->
                pbfnAcceleratorBusy( hvdm ) )                   /*          */
    {
      if( !(vdhBTS( &pvd->flVDMX2Video,
                    LOG2( VDMX2_8514ENGBUSY ) )) )
      {
        /*
        ** If ports are not being trapped, setup the hooks,
        ** so we can tell when the VDM accesses the I/O ports
        ** for status or more commands.
        ** It has to be done out of the VDM context,
        ** so setup the UpdateContext hook.
        ** Careful with VDM_UPDATEHOOK flag, do not use it.
        */
        if( pvd->flVDMXVideo & VDMX_NOIOTRAPPING )
          VDHArmContextHook(pvd->hhookUpdateContext,
                            pvd->hvdmVideo);
      }
      ResetEventSem( pvd->VdmSVGA.hev8514Busy );
      /* Must unfreeze other thread to let it finish */         /*          */
      if( !flFrozenOnEntry )                                    /*          */
      {                                                         /*          */
        vvSVGALockPopState( hvdm, bPrevUnlock );                /*          */
        VDHThawVDM( hvdm );                                     /*          */
        ReleaseMutexSem( pvd->hmxVideoState );                  /*          */
      }                                                         /*          */
      /* we don't care if it times out! */
      VDHWaitEventSem( pvd->VdmSVGA.hev8514Busy,
                       MAX_ENGINE_WAIT );
      if( !flFrozenOnEntry )                                    /*          */
      {                                                         /*          */
        RequestMutexSem( pvd->hmxVideoState );                  /*          */
        VDHFreezeVDM( hvdm );                                   /*          */
        bPrevUnlock = vvSVGALockPushState( hvdm );              /*          */
      }                                                         /*          */
      ulTimeOut += MAX_ENGINE_WAIT;
    }
    if( psCurAcceleratorInfo->pbfnAcceleratorBusy( hvdm ) )     /*          */
      psCurAcceleratorInfo->pfnAcceleratorReset( hvdm );
    vvSVGALockPopState( hvdm, bPrevUnlock );                    /*          */
    /* all clear, switch the VDM into bgnd */
    vdhBTR( &pvd->flVDMX2Video,          /* reset the flag */
            LOG2( VDMX2_8514ENGBUSY ) );
  }
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorUpdateIOState()
 *
 * DESCRIPTION   = Transfer harware I/O state to virtual
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 *                 This routine assumes we are in the foreground!
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvUpdateIOState
 *
 ***********************************************************************/

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

  if( vvAcceleratorChip() )             /*          */
    /* This should change in other accelerator code too! */     /*          */
    /* if( !(pvd->flVDMXVideo & VDMX_NOIOTRAPPING) */           /*          */
    if( !(pvd->flVDMXVideo & VDMX_INT2F) )                      /*          */
      /*
      ** Accelerator enabled,
      ** save all trapped accelerator registers.
      */
      psCurAcceleratorInfo->pfnAcceleratorUpdateIoState( hvdm );/*          */
}
/* Was v8514RestoreIOState */                                   /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorRestoreIOState()
 *
 * DESCRIPTION   = Transfer virtual I/O state to hardware
 *
 *                 This routine should NOT assume
 *                 that there IS an accelerator chip
 *
 *                 Assumes !(pvd->flVDMXVideo & VDMX_INT2F)                 
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvRestoreSVGAIOState
 *
 ***********************************************************************/

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

  if( vvAcceleratorChip() )             /*            */
    if( pvd->flVDMVideo & VDM_FGND )
    {                                                           /*          */
        psCurAcceleratorInfo->pfnAcceleratorRestoreIoState( hvdm );
    } /* endif (pvd->flVDMVideo & VDM_FGND) */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorCreate()
 *
 * DESCRIPTION   = Initialize Accelerator code
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVCreate (to decide whether to create semaphores)
 *      Calls accelerator creation routines to do specific stuff, such as
 *      initialize the shadow state of write-only regs and create private sems.
 ***********************************************************************/
BOOL    PRIVENTRY vvAcceleratorCreate(
  HVDM hvdm )
{
  register BOOL bTmp;

  psCurAcceleratorInfo = psCurAdapterInfo->psAcceleratorInfo;   /*          */
  VDMData.VdmSVGA.pvdmMMIOActive = pvdmStartupMMIOActive;              /*            */
  VDMData.VdmSVGA.npgMMIOActive = npgStartupMMIOActive;                /*            */

  if( !vvAcceleratorChip() )                                    /*            */
  {
    psCurAcceleratorInfo = NULL;
    return TRUE;
  }
  /* 8514IO semaphore should never be in use by non-accelerated SVGA devices */
  pVDMData(hvdm)->VdmSVGA.hev8514WakeUp = (HEVSEM) NULL;
  pVDMData(hvdm)->VdmSVGA.hev8514Busy = (HEVSEM) NULL;
  bTmp = CreateEventSem(&pVDMData(hvdm)->VdmSVGA.hev8514WakeUp)   /*          */
        && CreateEventSem(&pVDMData(hvdm)->VdmSVGA.hev8514Busy); /*          */
  if( psCurAcceleratorInfo->pbfnAcceleratorCreate)            /*            */
     if (!psCurAcceleratorInfo->pbfnAcceleratorCreate(hvdm))
        psCurAcceleratorInfo = NULL;            //no=op the accelerator info
  return( bTmp );                                               /*          */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorDestroy()
 *
 * DESCRIPTION   = Terminate Accelerator code
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVDestroy (to decide whether to destroy semaphores)
 *
 ***********************************************************************/
VOID    PRIVENTRY vvAcceleratorDestroy(
  HVDM hvdm )
{
  if (!vvAcceleratorChip())             /*            */
    return;
  if (VDMData.VdmSVGA.hev8514WakeUp)
    DestroyEventSem(VDMData.VdmSVGA.hev8514WakeUp);             /*          */
  if (VDMData.VdmSVGA.hev8514Busy)
    DestroyEventSem(VDMData.VdmSVGA.hev8514Busy);               /*          */
  if(psCurAcceleratorInfo->pbfnAcceleratorDestroy)            /*            */
    psCurAcceleratorInfo->pbfnAcceleratorDestroy(hvdm);
}

/***********************************************************************
 *
 * FUNCTION NAME = vvAcceleratorUpdateMemoryMapState()
 *
 * DESCRIPTION   = Notifies the accelerator code that memory map pages
 *                 are being touched, either as a result of a fault hook
 *                 or because the entire map is being enabled/disabled.
 *                 According to the current VDM state and the memory map.
 *                 this functions should either return physical (access
 *                 allowed) or black hole (access not allowed).
 *                 INVALID option should not be modified, when passed in!
 *                 Actual mapping is done by the caller.
 *                 Short path MMIO processing enables a single regions to
 *                 be declared as MMIO at the creation time (in EditTables)
 *                 function. This is a short solution to 1) lack of full MMIO
 *                 support thru pfnActiveMemoryMap & pfnUpdateMemoryMapState
 *                 and 2) disabled SVGA support (no PMI file).
 *                 The short path represent only a default MMIO region, which
 *                 will be overriden by actual pfnActiveMemoryMap & pfnUpdateMemoryMapState
 *                 if they are implemented. The default region is not mode sensitive, so
 *                 it can not cover all situation.
 *
 * INPUT         = HVDM, PVDM pvdmMMIO
 *
 * OUTPUT        = PULONG *flOption : mapping option for the page touched.
 *
 * RETURN-NORMAL = TRUE if VDM frozen as the result of mapping, FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVFaultHook
 *      vvEnableBuffer
 ***********************************************************************/
BOOL PRIVENTRY vvAcceleratorUpdateMemoryMapState(
        HVDM hvdm,
        PVDM pvdmFault,
        PULONG pflOption)
{
  register PVDMDATA pvd = pVDMData(hvdm);
  BOOL fFreeze = FALSE;
  if (psCurAcceleratorInfo && psCurAcceleratorInfo->pfnUpdateMemoryMapState)
  {
    /*
    ** Full MMIO support enabled for the adapter.
    */
    if (psCurAcceleratorInfo->pfnUpdateMemoryMapState( hvdm, pvdmFault, pflOption)
        && (*pflOption != VDHMT_INVALID))                  /*          */
    {
      vvFreezeVDM(hvdm,TRUE);
      /*
      ** When we return here, the state of VDM has changed, so we should
      ** now map invalid and let us evaluate again what is to be done.           
      */
      *pflOption = VDHMT_INVALID;
      return TRUE;
    }
  }
  else
  {
    /*
    ** short path. Map physical if FGND, BLACK_HOLE if background. Freeze only
    ** if background and non-VGA mode.
    */
    if (*pflOption == VDHMT_INVALID)
    {
       fFreeze = FALSE;
    }
    /*
    ** VGA BIOS modes will still enable the MMIO just to check if the accelerator
    ** is busy. When running in the background, map the memory to black hole, as
    ** to prevent them from writing to the accelerator state of the current controller
    ** owner. Black hole memory is not initialized and chances are they will find
    ** particular bits reset. However, should BIOS be waiting for a bit to go to 1,
    ** it will spin and hopefully time-out.
    ** Access to the page outside of the mode set will suspend the vdm.
    */
    else if(pvd->flVDMVideo & VDM_FGND)
    {
        *pflOption = VDHMT_PHYSICAL;
        fFreeze = FALSE;
    }
    else if(((pvd->ulBIOSMode & ~BIOSVINFO_DONTCLEAR)<= BIOSVMODE_CO320X200X256) ||
            (pvd->flVDMVideo & VDM_MODECHANGING))               /*            */

    {
        *pflOption = VDHMT_BLACK_HOLE;
        fFreeze = FALSE;
    }
    else
    {
        *pflOption = VDHMT_BLACK_HOLE;
        fFreeze = TRUE;            /* freeze the VDM */
    }
    if (fFreeze)
    {
      vvFreezeVDM(hvdm,TRUE);
      /*
      ** When we return here, the state of VDM has changed, so we should
      ** now map invalid and let us evaluate again what is to be done.           
      */
      *pflOption = VDHMT_INVALID;
      return TRUE;
    }
  }
  return FALSE;
}
#pragma  END_SWAP_CODE

