/*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 = VVSTATE.C
 *
 * DESCRIPTIVE NAME = Virtual Video Hardware State routines
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's hardware state routines.
 *
 *
 * FUNCTIONS
 *              vvUpdateAll()          Update all video state information
 *              vvUpdateIOState()      Update virtual I/O state from hardware
 *              vvUpdateMemoryState()  Update current memory state
 *              vvUpdateScreenState()  Update current screen state info
 *              vvUpdateModeData()     Update mode data for shield and/or mouse
 *              vvRestoreIOState()     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
#pragma  intrinsic(memcmp)
extern ULONG flVVD;

#pragma  BEGIN_SWAP_DATA

extern PLE pleFeatureWrite;                                     /*          */
extern PLE pleMiscOutWrite;                                     /*          */
extern PLE pleSEQIndx;                                          /*          */
extern PLE pleSEQData;                                          /*          */

#ifdef SVGA                                                     /*          */
extern PLE pleVGADACWrite;                                      /*          */
extern PLE pleVGADACMask;                                       /*          */
extern PSACCELERATORINFO psCurAcceleratorInfo;                  /*          */
#endif /* SVGA */                                               /*          */

extern LONG npgActive[];                                        /*          */

extern PPLE appleRestore [];                                    /*          */

#ifdef EGAVGA
extern PPLE appleUpdate [];                                     /*          */
extern PLE pleATC0;
#endif /* EGAVGA */

#ifdef SVGA                                                     /*          */
extern PLE pleATIVGAIndx;                                       /*          */
#endif /* SVGA */                                               /*          */

extern HVDD hvddMouse;
extern PBVDM pvdmPhysVRAM;

#ifdef   EGAVGA
extern PRLE aprleMemory[];                                      /*          */
#endif

extern PSADAPTERINFO psCurAdapterInfo;                          /*          */

#ifdef   SVGA                                                   /*          */
extern BYTE abCRTMask[];                                        /*          */
extern BYTE abGDCMask[];                                        /*          */
extern BYTE abSEQMask[];                                        /*          */
extern BYTE abATCMask[];                                        /*          */
extern BYTE abATIMask[];                                        /*          */
extern BYTE abCRTCBMask[];                                      /* JWK01 */
extern ULONG ulSVGAAdapterType;
extern ULONG ulSVGAChipType;
extern OEMINFO sOEMData;                                        /*          */
#endif                                                          /*          */

#pragma  END_SWAP_DATA

#ifdef   EGAVGA
   #pragma  BEGIN_GLOBAL_DATA
extern VVDRQ vvdrqVideo;
   #pragma  END_GLOBAL_DATA
#endif
#pragma  BEGIN_SWAP_CODE

#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvGetIOState()
 *
 * DESCRIPTION   = Get hardware according to specified register list
 *
 *                 This worker routine is used by vvUpdateIOState, and by
 *                 the pointer-draw code, to update the hardware shadow
 *                 information.  NOTE that none of the special
 *                 register-access conditions are applied, since we are
 *                 reading registers rather than writing them.
 *
 * INPUT         = hvdm  -> VDM
 *                 prle  -> register list
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvGetIOState(
  HVDM hvdm,
  register PPRLE pprle )                                        /*          */
{
  register BYTE bSaveIndex;                                     /*          */
  PPLE pple, ppleIndx, ppleLast = NULL;                         /*          */

  AssertTRUE(pVDMData(hvdm)->flVDMVideo&VDM_FGND);

  /*
  ** While not yet end of list
  */

  for( ;                                                        /*          */
       (*pprle);                                                /*          */
       pprle++ )                                                /*          */
  {
    pple = (*pprle)->rle_pple;                                  /*          */
#ifdef SVGA
    /*
    ** If port is valid only on specific SVGA, skip it.                   
    */
    if ((pple->sTrapBRegInfo.fTrapType & PORTF_NOTVALIDSVGAPORT)  ||
       ((*pprle)->rle_flags & PORTF_NOTVALIDSVGAPORT))
       continue;
#endif
    if ((*pprle)->rle_indx < 0)                                 /*          */
      /*
      ** Non-indexed register
      */
      vvInput( hvdm,                                            /*          */
               pple );                                          /*          */
    else
    {
      /*
      ** Indexed register
      */
      ppleIndx = pple->ppleBRegIndx;                            /*          */
      /*
      ** Save current index if new port
      */
      if( ppleIndx != ppleLast )                                /*          */
      {
        if( ppleLast )
          vvOutput( hvdm,                                       /*          */
                    ppleLast,                                   /*          */
                    bSaveIndex );
        ppleLast = ppleIndx;                                    /*          */
        bSaveIndex =
          vvInput( hvdm,                                        /*          */
                   ppleIndx )                                   /*          */
#ifdef SVGA                                                     /*          */
          | ((ppleIndx == &pleATIVGAIndx) ? 0x80 : 0x00)        /*          */
#endif /* SVGA */                                               /*          */
          ;                                                     /*          */
      }
      /*
      ** Set new index, and read its data
      */
      vvOutput( hvdm,                                           /*          */
                ppleIndx,                                       /*          */
                (*pprle)->rle_indx );                           /*          */
      vvInput( hvdm,                                            /*          */
               pple );                                          /*          */
    }
  } /* end for pprle */                                         /*          */
  if( ppleLast )
    vvOutput( hvdm,                                             /*          */
              ppleLast,                                         /*          */
              bSaveIndex );
}

/***************************************************************************
 *
 * FUNCTION NAME = vvUpdateIOState()
 *
 * DESCRIPTION   = Update virtual I/O state from hardware
 *
 *                 This refreshes some or all untrapped registers with their
 *                 current values for the specified VDM.  Only the VGA (and
 *                 some EGAs) have untrapped ports, and only the VGA supports
 *                 a partial update (since the memory-related ports are
 *                 always trapped on non-VGA hardware).
 *
 *                 If ALL, then all CRT, SEQ, and GDC registers are read and
 *                 stored in their appropriate virtual locations (as is the
 *                 DAC Mask register, which is also untrapped).  If not ALL,
 *                 then only the SEQ and GDC registers listed below are read
 *                 and recorded.
 *
 *                 Now always assumes VDM_FGND,                             
 *                 so check before call!                                    
 *
 * INPUT         = hvdm -> VDM
 *
 *                 fAll == TRUE is all untrapped registers to be read,
 *                         FALSE if some
 * OUTPUT        =
 *                 None
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvUpdateAll
 *
 * PSEUDO-CODE
 *                 if complete untrapped port update
 *                   read all untrapped regs
 *                 else
 *                   read all memory-related untrapped regs
 *
 ****************************************************************************/

VOID PRIVENTRY vvUpdateIOState(
  register HVDM hvdm,
  BOOL fAll )
{
  INT i;
  PPLE ppleIndx;
  BYTE bSaveIndex;
  register PPLE *ppple;
  register PRLE prle;

#ifdef   SVGA
  BYTE *pbData;
  BOOL flUnkReg;
#endif

  /*
  ** If complete update requested (for screen-switch or mode reset)
  */

  if (fAll)
  {
#ifdef   VGA
    vvVGAATCSaveState(hvdm);                                    /*          */
#endif

    for( ppple = appleUpdate;                                   /*          */
         *ppple;                                                /*          */
         ppple++ )                                              /*          */
      if( !((*ppple)->sTrapBRegInfo.fTrapType & PORTF_NOTVALIDSVGAPORT) ) /*                     */
      {
        if( !(*ppple)->ulBRegCount )
        {                                                       /*          */
          /*
          ** Non-indexed register
          */

#ifdef SVGA                                                     /*          */
          /*
          ** Reset the 32K HiColor DAC just in case                         
          ** it is left in the command mode state                           
          */

          if( *ppple == &pleVGADACMask )                        /*          */
            vvInput( INVALID_HVDM,                              /*          */
                     &pleVGADACWrite );                         /*          */
#endif /* SVGA */                                               /*          */

          /*
          ** And read the data and store it in shadow
          */
          vvInput( hvdm,                                        /*          */
                   *ppple );                                    /*          */
        }
        else /* end if not indexed */
        {                                                       /*          */
          ppleIndx = (*ppple)->ppleBRegIndx;                    /*          */
          /*
          ** Save current index first, before we change it
          */
          bSaveIndex = vvInput( hvdm,                           /*          */
                                ppleIndx )                      /*          */
#ifdef SVGA                                                     /*          */
                       | ((ppleIndx == &pleATIVGAIndx)          /*          */
                          ? 0x80                                /*          */
                          : 0x00)                               /*          */
#endif /* SVGA */                                               /*          */
                       ;
          /*
          ** Read all the readable indexed registers within this port.
          ** Writeonly register's shadow should be initialized by the vvAcceleratorCreate
          ** and this function will not update it, since its index should not
          ** be in the readable mask for the port.
          */
          for( i = 0;
               i < (*ppple)->ulBRegCount;
               i++ )
          {
#ifdef SVGA
            /*
            ** Indexed register should be updated only if it can be read.
            ** If it is not in the readable mask, skip it.                
            */
            if( !((*ppple)->pbBRegReadMask) ||
                ((*ppple)->pbBRegReadMask [i]) )                /*@V3.0YEE01*/
//@V3.0YEE01    ((*ppple)->pbBRegReadMask[i >> 3] & (1 << (i & 7))))
            {
#endif
                /*
                ** Set the index
                */
                vvOutput( hvdm,                                     /*          */
                        ppleIndx,                                 /*          */
                        (BYTE) i );
                /*
                ** And read the data and store it in shadow
                */
                vvInput( hvdm,                                      /*          */
                        *ppple );                                  /*          */
            }
#ifdef SVGA
          }
#endif
          /*
          ** Restore current index,
          ** leaving hardware state unchanged
          */
          vvOutput( hvdm,                                       /*          */
                    ppleIndx,                                   /*          */
                    bSaveIndex );
        } /* end else indexed */
      } /* end for ppple/if !PORTF_NOTRAP */                    /*          */

#ifdef VGA                                                      /*          */
    ((PSVGAINFO) psCurAdapterInfo)->pfnVGADACSave( hvdm );      /*          */
#endif /* VGA */
#ifdef SVGA                                                     /*          */
    vvAcceleratorUpdateIOState( hvdm );                         /*          */
#endif /* SVGA */                                               /*          */

  } /* endif (fAll) */

#ifdef VGA

  /*
  ** Else partial update only (for page fault or buffer reset)
  */

  else
    vvGetIOState( hvdm,
                  aprleMemory );                                /*          */
#endif /* VGA */
}

#endif /* EGAVGA */

/***************************************************************************
 *
 * FUNCTION NAME = vvUpdateMemoryState()
 *
 * DESCRIPTION   = Update current memory state
 *
 *                 This function returns a MEMORY_* constant indicating the
 *                 state of the VDM's video memory.
 *
 *                 Determination of video memory state is based on
 *                 registers/bits that define current addressibility.  In
 *                 the following, assume that all registers not specified
 *                 are not important to the state.  Also assume that all
 *                 bits not specified must be clear, unless otherwise noted;
 *                 "None" means that none must be set (all must be clear):
 *
 *
 *                     Register    Requirements for MEMORY_TEXT
 *
 *
 *                     SEQMEMMODE  None (ALPHA and EXTENDED are NOPs)
 *                     GDCESR      None
 *                     GDCROTATE   None
 *                     GDCREADMAP  None
 *                     GDCMODE     GDCMODE_ODDEVENDIFF
 *                     GDCMISC     GDCMISC_ODDTOEVEN (memory location is NOP)
 *                     GDCBITMASK  GDCMASK_ALL
 *
 *                 or:
 *
 *                     Register    Requirements for MEMORY_FONT
 *
 *                     SEQMAPMASK  SEQMAP_PLANE2
 *                     SEQMEMMODE  SEQMEM_ODDEVENSAME (ALPHA and EXTENDED are NOPs)
 *                     GDCESR      None
 *                     GDCROTATE   None
 *                     GDCREADMAP  Ignore(1)
 *                     GDCMODE     None
 *                     GDCMISC     None (memory location is NOP)
 *                     GDCBITMASK  GDCMASK_ALL
 *
 *                     (1) If a VDM tries to read font memory, this register
 *                         should be set to PLANE2.  However, this is
 *                         unenforceable.  There is no way to make memory
 *                         write-only, and disallowing random values in the
 *                         GDCREADMAP register could impact applications
 *                         that never intended to read the memory anyway.
 *
 *
 *                 Any other state is assumed to be MEMORY_GRFX.
 *
 *                 REG_GDCMISC Bits:
 *                   0x00 MEMORY_FONT
 *                   0x01 MEMORY_GRFX
 *                   0x02 (MEMORY_TEXT OR MEMORY_GRFX256)
 *                   0x03 (MEMORY_GRFX)
 *                   0x04 MEMORY_FONT
 *                   0x05 MEMORY_GRFX
 *                   0x06 (MEMORY_TEXT OR MEMORY_GRFX256)
 *                   0x07 (MEMORY_GRFX)
 *                   0x08 (MEMORY_FONT)
 *                   0x09 (MEMORY_GRFX)
 *                   0x0a MEMORY_TEXT
 *                   0x0b (MEMORY_GRFX)
 *                   0x0c (MEMORY_FONT)
 *                   0x0d MEMORY_GRFX2
 *                   0x0e MEMORY_TEXT OR MEMORY_GRFX256
 *                   0x0f MEMORY_CGAX
 *                 In parentheses is a reasonable guess
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = Returns one of the MEMORY_* constants
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 update active memory range
 *                 determine memory state by munging all
 *                   pertinent bits into a single dword and
 *                   checking its value
 *
 * CALLED BY
 *      vvUpdateAll
 *
 ****************************************************************************/

#define  SEQMAPMASK_SHIFT 0                     /* 4 bits                   */
#define  SEQMEMMODE_SHIFT (4-2)                 /* 1 bit                    */
#define  GDCREADMAP_SHIFT 5                     /* 3 bits                   */
#define  GDCMODE_SHIFT 8                        /* 7 bits                   */
#define  GDCMISC_SHIFT 15                       /* 2 bits, total of 17 bits */

VOID PRIVENTRY vvUpdateMemoryState(
  HVDM hvdm )
{
  register ULONG ul;
  register PVDMDATA pvd = pVDMData(hvdm);

  static PBVDM pvdmActive[] =
  {
    (PBVDM)EGAVGAMEM_START,
    (PBVDM)EGAVGAMEM_START,
    (PBVDM)MONOMEM_START,
    (PBVDM)CGAMEM_START,
  };

  /*
  ** Reset hardware copy state (unknown)
  */

  pvd->mstateCopy = MEMORY_NONE;

  /*
  ** Flag any change in the active memory range
  */

#ifdef   MONO
  ul = GDCMISC_32K_B0000;
#endif

#ifdef   CGA
  ul = GDCMISC_32K_B8000;
#endif

#ifdef   EGAVGA
  ul = pvd->aregGDCData[REG_GDCMISC] & GDCMISC_ADDRMASK;
#endif

  ul >>= ZEROBITS( GDCMISC_ADDRMASK );

  if( (pvd->pvdmPhysVRAMActive != pvdmActive[ul])
      || (pvd->npgPhysVRAMActive != npgActive[ul]) )
  {

    /*
    ** Update the active memory range
    */

    pvd->pvdmPhysVRAMActive = pvdmActive[ul];
    pvd->npgPhysVRAMActive = npgActive[ul];
    pvd->offPhysVRAMActive = pvd->pvdmPhysVRAMActive-pvdmPhysVRAM;

  }
  /*
  **  Obtain the latest memory map for SVGA/accelerators. This will define
  **  the MMIO base and range, which will be mapped by vvEnableBuffer function
  **  as well by the vvFaultHook appropriatelly.           
  */
#ifdef SVGA                                     /*            */
  if (psCurAcceleratorInfo && psCurAcceleratorInfo->pfnActiveMemoryMap)
       psCurAcceleratorInfo->pfnActiveMemoryMap( hvdm );
#endif

#ifdef EGAVGA
  /*
  ** Check requirements for being in GRFX256-mode on SVGA
  */
  if( ((PSEGAINFO) psCurAdapterInfo)->                          /*          */
         pbfnEGAPackedMode( hvdm ) )                            /*          */
    pvd->mstateVideo = MEMORY_GRFX256;
  else
#endif /* EGAVGA */

#ifndef MONO
    if( ((PSCGAINFO) psCurAdapterInfo)->                        /*          */
           pbfnCGAOddEvenMode( hvdm ) )                         /*          */
      pvd->mstateVideo = MEMORY_CGAX;
    else                                                        /*          */
      if( ((PSCGAINFO) psCurAdapterInfo)->                      /*          */
             pbfnCGAHighResMode( hvdm ) )                       /*          */
        pvd->mstateVideo = MEMORY_GRFX2;
      else                                                      /*          */
#ifdef EGAVGA
        /*
        ** If SET/RESET is enabled, or ROTATE options are enabled,
        ** or BITMASK has bits disabled, we are obviously not TEXT/FONT
        */
//      if( !(pvd->aregGDCData[REG_GDCMISC] & GDCMISC_ODDTOEVEN)    /*          */
//          || (pvd->aregGDCData[REG_GDCESR] & GDCESR_ALL)          /*          */
//          || (pvd->aregGDCData[REG_GDCROTATE] & GDCROTATE_ALL)    /*          */
//          || (pvd->aregGDCData[REG_GDCBITMASK] != GDCBITMASK_ALL) )/*          */
//      if( (pvd->aregGDCData [REG_GDCMISC] & GDCMISC_ALL)      /*          */
//          == (GDCMISC_64K_A0000 | GDCMISC_NOCHARGEN) )        /*          */
//        pvd->mstateVideo = MEMORY_GRFX;
        if( (pvd->aregGDCData [REG_GDCMISC] & GDCMISC_ADDRMASK) /*          */
            <= GDCMISC_64K_A0000 )                              /*          */
        {
          /*
          ** Extract and pack pertinent bits from various registers
          */

          ul = 0;                                               /*          */
          ul |= (pvd->aregSEQData [REG_SEQMAPMASK] & SEQMAP_ALL)/*          */
                << SEQMAPMASK_SHIFT;                            /*          */
          ul |= (pvd->aregSEQData [REG_SEQMEMMODE] & SEQMEM_ODDEVENSAME)/*          */
                << SEQMEMMODE_SHIFT;                            /*          */
          ul |= (pvd->aregGDCData [REG_GDCMODE] & GDCMODE_ALL)  /*          */
                << GDCMODE_SHIFT;                               /*          */
          ul |= (pvd->aregGDCData [REG_GDCMISC] & GDCMISC_ODDTOEVEN) /*          */
                << GDCMISC_SHIFT;                               /*          *//*          */
          /*
          ** Check requirements for being in FONT-mode.
          ** Plane 2 has to be selected while we are in a text mode.           
          */
//        if( !(pvd->aregGDCData [REG_GDCMISC]                  /*          */
//              & (GDCMISC_NOCHARGEN | GDCMISC_ODDTOEVEN)) )    /*          */
          if ((ul == ((SEQMAP_PLANE2 << SEQMAPMASK_SHIFT)        /*          */
                     | (SEQMEM_ODDEVENSAME << SEQMEMMODE_SHIFT)) )/*          */
             && !(pvd->aregGDCData [REG_GDCMISC] &                   /*          */
               (GDCMISC_NOCHARGEN | GDCMISC_ODDTOEVEN))              /*          */
             && !(pvd->aregATCData[REG_ATCMODECTRL] & GDCMISC_NOCHARGEN)) /*          */

            pvd->mstateVideo = MEMORY_FONT;
          else                                                  /*          */
            pvd->mstateVideo = MEMORY_GRFX;                     /*          */
        }                                                       /*          */
        else
          /*
          ** Check requirements for being in TEXT-mode
          */
//        if( ul == (((SEQMAP_PLANE0 | SEQMAP_PLANE1) << SEQMAPMASK_SHIFT) /*          */
//                   | (GDCMODE_ODDEVENDIFF << GDCMODE_SHIFT)   /*          */
//                   | (GDCMISC_ODDTOEVEN << GDCMISC_SHIFT)) )  /*          */
          if( (pvd->aregGDCData [REG_GDCMISC]                   /*          */
               & (GDCMISC_ODDTOEVEN | GDCMISC_NOCHARGEN))       /*          */
              == GDCMISC_ODDTOEVEN )                            /*          */
#endif /* EGAVGA */
#endif /* !MONO */
            pvd->mstateVideo = MEMORY_TEXT;
#ifdef EGAVGA
          else
//          /*                                                  /*          */
//          ** Check for A000 access while in text mode         /*          */
//          */                                                  /*          */
//          if( !(ul & (GDCMISC_NOCHARGEN << GDCMISC_SHIFT)) )  /*          *//*          */
//            pvd->mstateVideo = MEMORY_FONT;                   /*          *//*          */
//          else                                                /*          */
              /*
              ** We're still here,
              ** so it must be some GRFX-mode
              */
              pvd->mstateVideo = MEMORY_GRFX;
#endif /* EGAVGA */
#ifdef SVGA             //           start
  /*
  ** Definition of enhanced mode on dumb-frame buffer adapters:
  ** packed linear memory configuration using more than 256K of VRAM.
  ** On accelerators:
  ** above or any memory configuration when engine is enabled.
  **
  ** Implies:
  **   Linear memory shadow
  **   Freezing if background unless background execution cmd flag is set.
  **            let vvSVGAUpdateModeData set the VDMX_ENHANCEDMODE in case that
  ** vvUpdateMemoryState didn't get to set it.
  */
  pvd->VdmSVGA.usCurrentBank = (USHORT) BANK0;
  if( (pvd->mstateVideo == MEMORY_GRFX256)
      && ((pvd->ulBIOSMode & ~BIOSVINFO_DONTCLEAR)
          > BIOSVMODE_CO320X200X256) )                            /*@V3.0MNH03*/
    pvd->flVDMXVideo |= VDMX_ENHANCEDMODE;
  else
    pvd->flVDMXVideo &= ~VDMX_ENHANCEDMODE;
  if( ((pvd->ulBIOSMode & ~BIOSVINFO_DONTCLEAR)
        > BIOSVMODE_CO320X200X256)                                /*          */
      && (pvd->flVDMXVideo & VDMX_INT2F) )                        /*          */
  {
    /*
    ** If int 2F is enabled, we want to give them full access at once as
    ** to speed up their performance. We also want to mark them as enhanced
    ** as to freeze them if mode set was executing in the background.
    */
    pvd->flVDMXVideo |= VDMX_ENHANCEDMODE;
    pvd->pvdmPhysVRAMActive = (PVDM) EGAVGAMEM_START;
    pvd->npgPhysVRAMActive = EGAVGAMEM_PAGES;
  }

#endif          /* SVGA */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvUpdateModeData()
 *
 * DESCRIPTION   = Update mode data for shield and/or mouse
 *
 *                  Note this is not only called by UpdateScreenState, but
 *                  also anywhere where new mode information needs to be
 *                  posted to Shield.  Currently, the only such places are
 *                  where we freeze/thaw a VDM (since that indicator is part
 *                  of the mode event data).
 *
 * INPUT         = hvdm  -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvUpdateScreenState
 *      vvChangeCodePage
 *      vvFreezeVDM
 *      vvThawVDM
 *
 ****************************************************************************/

VOID PRIVENTRY vvUpdateModeData(
  HVDM hvdm )
{
  VMSSIZE vmssNew;
  register PVDMDATA pvd = pVDMData(hvdm);

  pvd->vvMode.vvm_ulAdapter = ADAPTER_TYPE;
  pvd->vvMode.vvm_ulFormat = FORMAT_CGA;
  pvd->vvMode.vvm_ulDDFormat = 0;
  pvd->vvMode.vvm_flMode = 0;
  pvd->vvMode.vvm_nPlanes = 0;
  pvd->vvMode.vvm_nBitCount = 0;
  pvd->vvMode.vvm_fSuspended = SUSPEND_NONE;

#ifdef SVGA                                                     /*          */
  if (psCurAdapterInfo->pfnUpdateModeData)
    psCurAdapterInfo->pfnUpdateModeData( hvdm );                /*          */
#endif
#ifndef SVGA
  if (pvd->flVDMVideo & VDM_FROZEN)                             /*          */
  {
    pvd->vvMode.vvm_fSuspended = SUSPEND_OUT_OF_MEMORY;         /*          */
#else
  if( (pvd->flVDMVideo & VDM_FROZEN) ||                         /*          */
      (pvd->flVDMX2Video & VDMX2_8514BLOCKED) ||
      (
        ((pvd->ulBIOSMode & ~BIOSVINFO_DONTCLEAR) > 0x13)
          && (pvd->flVDMVideo & VDM_WINDOWED)
          && (pvd->mstateVideo > MEMORY_TEXT)
        ) ||
      (
        ((pvd->flVDMXVideo & VDMX_ENHANCEDMODE)
          && !(pvd->flVDMVideo & VDM_FGND))
      ))
  {
    pvd->vvMode.vvm_fSuspended = SUSPEND_UNSUPPORTED_MODE;
#endif                                  /*          */

    if (!(pvd->flVDMVideo&VDM_GRFXALLOWED)

#ifdef   EGAVGA
        || !(flVVD&VVD_PMBGND) && vvdrqVideo.vvd_nbReserved ==
           ALL_RESERVED
#endif /* EGAVGA */
         )
    {
       pvd->vvMode.vvm_fSuspended = SUSPEND_UNSUPPORTED_MODE;
    }
  }

  if (pvd->mstateVideo >= MEMORY_CGAX)
  {
    pvd->vvMode.vvm_ulFormat = FORMAT_BITMAP;
    pvd->vvMode.vvm_flMode |= MODE_SUP_YSCALE2;

    if (pvd->vvMode.vvm_nCols == 320)
      pvd->vvMode.vvm_flMode |= MODE_SUP_XSCALE2;
    pvd->vvMode.vvm_nPlanes = 1;
    pvd->vvMode.vvm_nBitCount = pvd->nBitsPixel * pvd->nPlanes;

    if (pvd->mstateVideo == MEMORY_GRFX && pvd->vvMode.vvm_nBitCount ==
       4)
    {

      /* FLAG:  - Until the DDBitmap code supports scaling,           */
      /*          it must be disabled for all cases....               */

      pvd->vvMode.vvm_ulDDFormat = DDFORMAT_4PLANE;
      pvd->vvMode.vvm_flMode &= ~(MODE_SUP_XSCALE2|MODE_SUP_YSCALE2);
    }

    /*
    ** Convert actual bitcount into a supported value
    */

    if (pvd->vvMode.vvm_nBitCount > 1)

      if (pvd->vvMode.vvm_nBitCount <= 4)
        pvd->vvMode.vvm_nBitCount = 4;

      else

        if (pvd->vvMode.vvm_nBitCount <= 8)

          pvd->vvMode.vvm_nBitCount = 8;
  }

  /*
  ** Refresh mode data for Shield
  */

  vvAddEvent(hvdm,
             VVDEVENT_MODE,
             &pvd->vvMode,
             0);

  /*
  ** Refresh cursor data since visibility can change based on mode
  */

  vvUpdateCursorData(hvdm);

  /*
  ** Don't tell the mouse driver *anything* unless we're active
  */

  if (pvd->flVDMVideo&VDM_IOINIT && pvd->flVDMXVideo&VDMX_ACTIVE)
  {
    vmssNew.vmss_nb = sizeof(VMSSIZE);
    vmssNew.vmss_lMode = pVDMBase(hvdm)->rb_bVMode&~BIOSVINFO_DONTCLEAR;
    vmssNew.vmss_ulWidth = pvd->vvMode.vvm_nCols
       *pvd->vvMode.vvm_ulCellWidth;
    vmssNew.vmss_ulHeight = pvd->vvMode.vvm_nRows
       *pvd->vvMode.vvm_ulCellHeight;
    vmssNew.vmss_ulCellWidth = pvd->vvMode.vvm_ulCellWidth;
    vmssNew.vmss_ulCellHeight = pvd->vvMode.vvm_ulCellHeight;

    /*
    ** If this is a complete state reinitialization (eg, mode changed
    ** or if the first 6 (mode-related) fields of vmssNew differ...
    */

    if (!(pvd->flVDMVideo&VDM_STATEINIT) || memcmp
       (&pvd->PtrData.vmssVideo,
        SSToDS(&vmssNew),
        6*sizeof(ULONG)))
    {

      /*
      ** Make sure the mouse is in a stable state
      */

      pvd->PtrData.fPtrFrozenVideo++;

      /*
      ** Update the mouse mode data
      */

      pvd->PtrData.vmssVideo = *(PVMSSIZE)SSToDS(&vmssNew);

      /*
      ** Initialize the pointer-specific portions of the data
      */

      vvPtrReset(hvdm);

      /*
      ** And finally, notify the virtual mouse driver
      */

      if (hvddMouse)
        VDHRequestVDD(hvddMouse,
                      hvdm,
                      VMDEVREQ_SETSIZE,
                      &pvd->PtrData.vmssVideo,
                      NULL);
      pvd->PtrData.fPtrFrozenVideo--;
    }
  }
  /*
  **            All evaluation of ENHANCED_MODE for SVGA's is delegated
  ** to vvUpdateMemoryState function. SVGA adapter specific VVID pfnUpdateModeData
  ** can modify the enhanced flag should our evalutation of linear memory
  ** organization be at fault.
  */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvUpdateScreenState()
 *
 * DESCRIPTION   = Update current screen state info
 *
 *                 This function updates the state information for visible
 *                 VDM VRAM.  This should be called only after the memory
 *                 state has been updated.
 *
 *                 Determination of visibility size is based on the number
 *                 of scan lines visible (divided by the number of scan
 *                 lines per character row if in text mode).
 *
 *                     Register        Use
 *
 *                     CRTVERTDSPEND   This (+1) is total scan lines showing
 *
 *                     CRTOVERFLOW     Bit 1 contains bit 8 for CRTVERTDSPEND
 *
 *                     CRTMAXSCAN      This (+1) is total scan lines
 *                                     per character row
 *
 *                     CRTSTARTADDRHI  This is active-relative start
 *                                     address (high byte)
 *
 *                     CRTSTARTADDRLO  This is active-relative start
 *                                     address (low byte)
 *
 *
 * INPUT         = hvdm -> VDM
 *                 fUpdate == TRUE to update mode information, FALSE to not
 *
 * OUTPUT        = Visibility state info updated
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvUpdateAll
 *
 ****************************************************************************/

VOID PRIVENTRY vvUpdateScreenState(HVDM hvdm,BOOL fUpdate)
{
  ULONG offset,u;
  register PVDMDATA pvd = pVDMData(hvdm);
  register ULONG nBytes;
  USHORT usBytesPerRow;
  USHORT usRows, usRowSplit;

  offset = ((PSCGAINFO) psCurAdapterInfo)->                     /*          */
             pulfnCGAStartAddr( hvdm );
  if( pvd->mstateVideo <= MEMORY_FONT )
  {
    pvd->vvMode.vvm_ulCellWidth = 8;
    pvd->vvMode.vvm_ulCellHeight =
     (pvd->aregCRTData [REG_CRTMAXSCAN] & 0x1F) + 1;
    /*
    ** If no true screen state exists yet, pick reasonable defaults
    */
    if( pvd->vvMode.vvm_ulCellHeight <= 1 )
      pvd->vvMode.vvm_ulCellHeight = 8;
  }
  else
  {
    /*
    ** Must be some graphics mode,
    ** so set up defaults for that assumption
    */
    pvd->vvMode.vvm_ulCellWidth = 1;
    pvd->vvMode.vvm_ulCellHeight = 1;
  }

  /*
  ** Get # of bytes across (all 7+ bits)
  */

  usBytesPerRow = ((PSCGAINFO) psCurAdapterInfo)->              /*          */
                    pusfnCGAHorzDspEnd( hvdm );                 /*          */

  /*
  ** Get # scan lines visible (all 9+ bits)
  */

  usRows = ((PSCGAINFO) psCurAdapterInfo)->                     /*          */
             pusfnCGAVertDspEnd( hvdm )                         /*          */
#ifdef SVGA                                                     /*          */
          << psCurAdapterInfo->pbfnSVGAInterlaced( hvdm )       /*          */
#endif /* SVGA */                                               /*          */
          ;

#ifdef EGAVGA                                                   /*          */
  /*
  ** Get split-screen row #, if any (all 9+ bits)
  */

  usRowSplit = ((PSEGAINFO) psCurAdapterInfo)->                 /*          */
                 pusfnEGAVertLineCmp( hvdm )                    /*          */
#ifdef SVGA                                                     /*          */
              << psCurAdapterInfo->pbfnSVGAInterlaced( hvdm )   /*          */
#endif /* SVGA */                                               /*          */
              ;

  /*
  ** FLAG: 18-Sep-90
  ** This is NOT "support" for split-screen apps;  it simply prevents us
  ** from blowing up on them, by limiting our attention to just the top
  ** portion of the screen.  There is much more work required throughout the
  ** driver to properly reset compare/copy operations at the "spliting"
  ** scanline, and because such apps are almost never encountered, the work
  ** is low priority.
  */

  if( usRows > usRowSplit )
    usRows = usRowSplit;

  if( pvd->aregCRTData [REG_CRTMAXSCAN] & CRTMAXSCAN_200CONV )
    usRows /= 2;
#endif /* EGAVGA */                                             /*          */

  pvd->nBitsPixel = ((PSCGAINFO) psCurAdapterInfo)->            /*          */
                      pusfnCGABitsPerPixel( hvdm );             /*          */

  /*
  ** If no true screen state exists yet, pick reasonable defaults
  */

  if( usBytesPerRow <= 1 )
    usBytesPerRow = 80;

  if( usRows <= 1 )
    usRows = 200;
  pvd->nPlanes = 1;

  /*
  ** If text mode, account for attribute bytes and such now
  */

  if (pvd->mstateVideo <= MEMORY_FONT)
  {
    if (!(usRows /= pvd->vvMode.vvm_ulCellHeight))              /*          */
      usRows++;                                                 /*          */
    pvd->vvMode.vvm_nCols = usBytesPerRow;
    usBytesPerRow *= 2;
    offset *= 2;
  }
  else
  {
    /*
    ** Must be some graphics mode, so set up defaults for that assumption
    */
    pvd->vvMode.vvm_nCols = usBytesPerRow * 8;

#ifdef   EGAVGA
    u = pvd->aregATCData [REG_ATCPLANEENABLE] & SEQMAP_ALL;
    if (u == 0x03)
      pvd->nPlanes = 2;
    else if (u == 0x07)
      pvd->nPlanes = 3;
    else if (u != 0x01)
      pvd->nPlanes = 4;
#endif
  }

#ifndef  MONO
  /*
  ** If CGA modes 4/5, make minor adjustments
  */
  if( pvd->mstateVideo == MEMORY_CGAX )                         /*          */
  {
    usBytesPerRow *= 2;
    pvd->nPlanes = 1;
  }
#endif /* MONO */

#ifdef   CGA
  if( pvd->mstateVideo == MEMORY_GRFX2 )                        /*          */
    pvd->vvMode.vvm_nCols *= 2;
#endif

#ifdef   EGAVGA
  if( ((PSEGAINFO) psCurAdapterInfo)->                          /*          */
        pbfnEGAPackedMode( hvdm ) )                             /*          */             /*          */
  {
    pvd->nPlanes = 1;
    pvd->vvMode.vvm_nCols /= (pvd->nBitsPixel >> 3);            /*          */
    usRows /=                                                   /*          */
      ((pvd->aregCRTData [REG_CRTMAXSCAN] & 0x1F) + 1);         /*          */
//  Holds for ATI:                                              /*          */
//  usBytesPerRow *= 8; /* Bits per pixel */                    /*          */
//  usBytesPerRow /=                                            /*          */
//    (((pvd->aregATCData [REG_ATCMODECTRL] & 0x40)             /*          */
//      >> ZEROBITS( 0x40 )) + 1);                              /*          */
//  pvd->vvMode.vvm_nCols /=                                    /*          */
//    (((pvd->aregATCData [REG_ATCMODECTRL] & 0x40)             /*          */
//      >> ZEROBITS( 0x40 )) + 1);                              /*          */
//  The adjustment below should NOT depend on the mode number.  /*          */
//  It should depend on the hardware bits!                      /*          */
//  And it might be adapter dependent!                          /*          */
    /*
    ** If VGA modes 13h (256-color), make minor adjustments
    */
    if( ((pvd->ulBIOSMode & ~BIOSVINFO_DONTCLEAR)
         == BIOSVMODE_CO320X200X256)                            /*          */
        && !(pvd->flVDMXVideo & VDMX_ENHANCEDMODE) )            /*          */
    { /* A TRUE mode 13h */
      usBytesPerRow *= 4;
      pvd->vvMode.vvm_nCols /= 2;
    }

#ifdef SVGA                                                     /*          */
    /*!! Move this code to vvTrident somehow! */                /*          */
    if (ulSVGAAdapterType == TRIDENT_ADAPTER)
    {                                   /* ALERT:640x480x256 */ /*          */
      if( (usBytesPerRow > 128)
          && ((pvd->ulBIOSMode & ~BIOSVINFO_DONTCLEAR)
              != BIOSVMODE_CO320X200X256) )                     /*          */
      {                                 /* detects 160 bytes */ /*          */
        usBytesPerRow /= 2;
        pvd->vvMode.vvm_nCols /= 2;     /* ================= */ /*          */
      }
      if( usBytesPerRow == 128 )
        usRows = 768;
    }
#endif /* SVGA */                                               /*          */

  }
#endif /* EGAVGA */

#ifdef SVGA                                                     /*          */
  /*!!This should probably be for EGAVGA */                     /*          */
  /*
  ** ulLogicalBytes represents the screen width in bytes, not in pixels.
  */
  pvd->VdmSVGA.ulLogicalBytes =                                 /*          */
    ((pvd->flVDMVideo & VDM_MODECHANGING)                       /*          */
     ? 0                                                        /*          */
     : ((PSCGAINFO) psCurAdapterInfo)->                        /*          */
          pusfnCGAHorzLogEnd( hvdm ));                            /*          */                     /*          */
//                  << (1                                                   /*          */
//                      + !(pvd->aregCRTData [REG_CRTMODECTRL] & 0x40)      /*          */
//                      + ((PSEGAINFO) psCurAdapterInfo)->                  /*          */
//                          pbfnEGAPackedMode( hvdm ))) );                  /*          */
//                     )));                                                   /*            */
  vvAcceleratorUpdateScreenState( hvdm );                       /*          */
#endif /* SVGA */                                               /*          */

  if( !pvd->nBitsPixel )
    pvd->nPixelsByte = 0;
  else
    pvd->nPixelsByte = 8 / pvd->nBitsPixel;
  pvd->vvMode.vvm_nRows = usRows;                               /*          */

  /*
  ** Now get total size by multiplying bytes across by # rows
  */
  pvd->nbVRAMRow = usBytesPerRow;
  nBytes = usBytesPerRow * usRows;

#ifndef  MONO
  /*
  ** If operating in compatibility mode, make odd/even size adjustment
  */
  pvd->offOddBank = 0;
  if( (pvd->mstateVideo == MEMORY_CGAX)                         /*          */
      || (pvd->mstateVideo == MEMORY_GRFX2) )                   /*          */
  {
    offset *= 2;
    pvd->offOddBank = 8 * 1024;
    nBytes = pvd->offOddBank + (nBytes / 2);                    /*          */
  }
#endif /* MONO */


  /*
  ** Sanity check: visible range must be restricted to active memory
  ** On SVGA's, the offset or bytes may be evaluated out of range, due to
  ** erroneous emulation of the lock state. Should this happen, assume
  ** that offset is 0. We can't presently virtualize a mode which doesn't
  ** start within the active VRAM. Furthermore, VGA can't virtualize a mode
  ** which requires mode than 256K. ModeBytes represents total size of the VRAM
  ** touched by the mode.                                 
  */
#ifndef SVGA
  // for SVGA, mode bytes are calculated in vvsvgamaxbanks.
  pvd->nModeBytes = (pvd->vvMode.vvm_nCols / 8);
  pvd->nModeBytes *= pvd->vvMode.vvm_nBitCount;
  pvd->nModeBytes *= pvd->vvMode.vvm_nRows;
#else
  /*
  ** Evaluate the memory consumption only after the mode has been evaluated.
  */
  vvSVGAMaxBanks(hvdm);                         //will set new usMaxBanks
  if (pvd->VdmSVGA.usMaxBanks > (USHORT) MAX_VGA_BANK)
  {
     pvd->VdmSVGA.usCurrentBank = (USHORT)
              (*psCurAdapterInfo->pulfnSVGAGetBank)
                                ( hvdm,
                                TRUE );                   /* get write bank     */
  }
  else
    pvd->VdmSVGA.usCurrentBank = BANK0;
#endif
  if (offset >= (pvd->npgPhysVRAMActive * PAGESIZE))
    offset = 0;                 //          
  if( (offset + nBytes) > (pvd->npgPhysVRAMActive * PAGESIZE) )
    nBytes = (pvd->npgPhysVRAMActive * PAGESIZE) - offset;

  /*
  ** Now to answer the all-important question:  what's visible?
  */
  pvd->pvdmPhysVRAMVisible = pvd->pvdmPhysVRAMActive + offset;
  pvd->offPhysVRAMVisible = offset;
  pvd->nbPhysVRAMVisible = nBytes;

  /*
  ** Now that we have all the heights and widths worked out,
  ** update the rest of the mode data structure and post mode event
  */
  if (fUpdate)
    vvUpdateModeData( hvdm );
}

/***************************************************************************
 *
 * FUNCTION NAME = vvUpdateAll()
 *
 * DESCRIPTION   = Update all video state information
 *
 *                 This is called at the following times:
 *                     + video page faults
 *                     + screen-switch requests
 *                     + INT 10h mode-change completions
 *                     + INT 10h font-change completions
 *
 * INPUT         = hvdm -> VDM
 *                 fAll == TRUE to read all untrapped registers, FALSE if not
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVFaultHook (hvdm, FALSE)
 *      VVCreate
 *      VVInt10SetModeReturn
 *      VVInt10Return (TRUE)
 *      VVWriteIBMApertureCtrlFgnd (TRUE)
 *      VVSetBgnd
 *      VVSetFgnd
 *
 ****************************************************************************/

VOID PRIVENTRY vvUpdateAll(HVDM hvdm,BOOL fAll)
{
  register PVDMDATA pvd = pVDMData(hvdm);
#ifdef SVGA                                                     /*          */
  BOOL bPrevUnlock;                                             /*          */
#endif /* SVGA */                                               /*          */

  /*
  ** Can't do complete update unless all I/O initialization is done
  */

  if (!(pvd->flVDMVideo&VDM_IOINIT) && fAll)
    return ;
  RequestMutexSem(pvd->hmxVideoState);

#ifdef   EGAVGA

  /* Move from vvUpdateIOState to do it ONCE! */                /*          */
#ifdef SVGA                                                     /*          */
  bPrevUnlock = vvSVGALockPushState( hvdm );                    /*          */
#endif /* SVGA */                                               /*          */
  if( pvd->flVDMVideo & VDM_FGND )                              /*          */
  {                                                             /*          */
#ifdef SVGA                                                     /*          */
    psCurAdapterInfo->pfnSVGAUpdateIoState( hvdm );             /*          */
#endif /* SVGA */                                               /*          */

    /*
    ** Update specified set of virtual registers
    */

    vvUpdateIOState( hvdm,
                     fAll );
  }                                                             /*          */
#endif /* EGAVGA */

  /*
  ** Get new memory state, if any
  */

  vvUpdateMemoryState( hvdm );

  /*
  ** KLUDGE alert: for video cards that have strange tendencies to go
  ** off and write to memory in graphics modes as part of their INT 10h
  ** *text* mode initialization, we pretend that they are writing to
  ** font memory, so that we don't end up freezing them.  This is only
  ** useful for background VDMs in the middle of certain INT 10h mode
  ** changes;  foreground VDMs can already do whatever they want....
  */

  if ((pvd->flVDMVideo&(VDM_FGND|VDM_MODECHANGING)) == VDM_MODECHANGING)
  {

    if (pvd->ulBIOSMode <= BIOSVMODE_CO80 || pvd->ulBIOSMode ==
       BIOSVMODE_MONO80)

      if (pvd->mstateVideo > MEMORY_FONT)
        pvd->mstateVideo = MEMORY_FONT;
  }

  /*
  ** Convert virtual buffer page states to new state, if any.
  ** If the memory state has changed in SVGA, we invalidate the current
  ** pages and enable the fault hooks, which is in contrast with VGA,
  ** which just converts the previos page states.
  */

  if (vvUpdatePageStates(hvdm))
  {
#ifdef   EGAVGA
    if( pVDMData( hvdm )->flVDMVideo & VDM_FGND )               /*          */
      if (!fAll)
        vvUpdateIOState( hvdm,
                         TRUE );
#endif
    fAll = TRUE;
  }

  /*
  ** If we have to update everything
  */

  if (fAll && !(pvd->flVDMVideo&VDM_DYING))
  {

    /*
    ** Update screen state information
    */

    vvUpdateScreenState( hvdm, TRUE );

    /*
    ** See if this is a mode that requires a shadow buffer
    */

    vvAllocShadowBuffer(hvdm);
    pvd->flVDMVideo |= VDM_STATEINIT;

#ifdef   VDDDEBUGALL
    PRINTDEBUG("New video state: %01x (%s)\n",
               pvd->mstateVideo,
               apszPageStates[pvd->mstateVideo]);
#endif
  }

  /*
  ** Special-case I/O trapping may need enabling/disabling
  */

  if (hvdm == CURRENT_VDM)
    VVSpecialCaseIO( NULL,
                     NULL );
#ifdef SVGA                                                     /*          */
  vvSVGALockPopState( hvdm, bPrevUnlock );                      /*          */
#endif /* SVGA */                                               /*          */
  ReleaseMutexSem(pvd->hmxVideoState);
}

/***************************************************************************
 *
 * FUNCTION NAME = vvRestoreIOState()
 *
 * DESCRIPTION   = Transfer virtual I/O state to hardware
 *
 *                 ATI requires that registers be set in a particular order.
 *                 After loading the ATI extended registers, the Misc Output
 *                 must be set before any reset condition clears out CLK
 *                 sensitive bits in the extended register range.  By virtue
 *                 of the appleRestore [] ordering, the ATI regs are restored
 *                 last, and we can then do the Misc.  Output register load
 *                 at the end of this routine.  The desired ordering as per
 *                 their documentation is:
 *
 *                     Start synchronous reset (Sequencer reg 0)
 *                     ATI Extended regs
 *                     Miscellaneous Output reg
 *                     Sequencers (1-4)
 *                     End Sequencer reset
 *                     Load CRT, ATC, GDC and then DACs
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVSetFgnd
 *      VVSetBgnd
 *
 ****************************************************************************/

VOID PRIVENTRY vvRestoreIOState(register HVDM hvdm)
{
  FLAGS flCond;
  register PPLE *ppple;
  register INT i,j;
  PORT portIndx,portData;
  register PORT portStatus;

#ifdef   SVGA
  BYTE *pbData;
  BOOL flUnkReg;
#endif


  if (pVDMData(hvdm)->mstateVideo == MEMORY_NONE)
  {
    return ;
  }

  for ( ppple = appleRestore;                                   /*          */
        *ppple;                                                 /*          */
        ++ppple )                                               /*          */
    if( !((*ppple)->sTrapBRegInfo.fTrapType & PORTF_NOTVALIDSVGAPORT) )   /*                     */
    {
      portData = ((PSCGAINFO) psCurAdapterInfo)->               /*          */
                   pportfnCGAAdjustedPort(                      /*          */
                     &(*ppple)->sTrapBRegInfo );                /*          */
      if( !(*ppple)->ulBRegCount )                              /*          */
      {
        /*
        ** Non-indexed port
        */

        flCond = 0;

        if ((*ppple)->flBRegResetSeq)
          flCond |= REGCOND_RESETSEQ;

        if ((*ppple)->flBRegWaitVert)
          flCond |= REGCOND_WAITVERT;

        if ((*ppple)->flBRegWaitHorz)
          flCond |= REGCOND_WAITHORZ;

#ifdef   EGAVGA
        /*
        ** Use vvShadowOutput since
        ** handles register conditions
        */
        vvShadowOutput(
          hvdm,
          0,
          portData,
          -1,
          *pVDM( hvdm,
                 PBYTE,
                 (*ppple)->sTrapBRegInfo.pvTrapWriteShadow ),
          NULL,
          NULL,
          flCond );
#else /* EGAVGA */
        /*
        ** On MONO/CGA cards,
        ** there are no conditions to worry about
        */
        vvOutput( INVALID_HVDM,                                 /*          */
                  *ppple,                                       /*          */
                  *pVDM( hvdm,                                  /*          */
                         PBYTE,                                 /*          */
                         (*ppple)->
                           sTrapBRegInfo.pvTrapWriteShadow) );  /*          */
#endif /* EGAVGA */
      }
      else
      {
        /*
        ** Indexed port
        */
        portIndx =
          ((PSCGAINFO) psCurAdapterInfo)->                      /*          */
            pportfnCGAAdjustedPort(                             /*          */
              &(*ppple)->ppleBRegIndx->sTrapBRegInfo );         /*          */
        if( (*ppple)->sTrapBRegInfo.fTrapType                   /*          */
            & PORTF_INDEXDATA )                                 /*          */
          /*
          ** Ports used for both index and data
          ** need their flip-flop reset, like so
          */
          vvInput( INVALID_HVDM,                                /*          */
                   &pleFeatureWrite );  /* =STATUS1 for read */ /*          */
        if( !((*ppple)->sTrapBRegInfo.fTrapType                 /*          */
              & PORTF_AUTOINC) )                                /*          */
        {                                                       /*          */
#ifdef   SVGA                                                   /*          */
          pbData = (*ppple)->pbBRegMask;                        /*          */
          flUnkReg = !pbData;                                   /*          */
#endif /* SVGA */                                               /*          */
          /*
          ** Normal case (non-auto-increment)
          */
#ifdef VGA
          if( (*ppple)->sTrapBRegInfo.fTrapType                 /*          */
              & PORTF_CRTCTRL )                                 /*          */
          {
            /*
            ** On VGA, insure CRT controller not write-protected
            */
            PBYTE  pData = pVDM( hvdm,                          /*           */
                            PBYTE,
                            (*ppple)->sTrapBRegInfo.pvTrapWriteShadow );
            OUTW( portIndx,
                  REG_CRTVERTENDRTRC | ((pData[REG_CRTVERTENDRTRC] & 0x7F) << 8));                      //          
          }
#endif /* VGA */

#ifdef   MONO                                                   /* 73042 */
          /*                                                       73042
          ** Only restore cursor related register values           73042
          */                                                    /* 73042 */

          for (i = 0x0e, j = 1;
               i <= 0x0f;
               ++i, j <<= 1)                                    /* 73042 */
#else /* MONO */                                                /* 73042 */
          for (i = 0, j = 1;
               i < (*ppple)->ulBRegCount;
               ++i, j <<= 1)
#endif /* MONO */                                               /* 73042 */
          {
            flCond = 0;
            if ((*ppple)->flBRegResetSeq&j)
              flCond |= REGCOND_RESETSEQ;
            if ((*ppple)->flBRegWaitVert&j)
              flCond |= REGCOND_WAITVERT;
            if ((*ppple)->flBRegWaitHorz&j)
              flCond |= REGCOND_WAITHORZ;

#ifdef   EGAVGA

#ifdef   SVGA                                                   /*          */

            /* do some specifics, */
            /* see 'Port-list entry'in vvdp.h */
            /* Sensitive registers are indices: */
            /* 0xA4, 0xF8, 0xFD.*/

            if( (ulSVGAAdapterType == VIDEO7_ADAPTER)
                && ((*ppple)->ppleBRegIndx == &pleSEQIndx) )    /*          */
            {
              if ((i == 0xA4) || (i == 0xF8) || (i == 0xFD))
                flCond |= REGCOND_RESETSEQ;
            }
            /* pbData may be undefined! */                      /*          */
            /* do not look at it if flUnkReg! */                /*          */
            if( flUnkReg                                        /*          */
                || pbData [i])                                  /*@V3.0YEE01*/
//@V3.0YEE01    || (pbData [i >> 3] & (1 << (i & 7))) )         /*          */
            {
              if( !flUnkReg
                     /* Not all bits on! */
                  && (pbData [i] != 0xff) )
              {
                /* read value from shadow                         @V3.0YEE01
                /* and with pbData
                /* read value from hw
                /* and with complement of pbData
                /* or both values
                /* write back to hw and shadow */
                vvOutput( INVALID_HVDM,
                          (*ppple)->ppleBRegIndx,
                          (BYTE) i );
                pVDM( hvdm,
                      PBYTE,
                      (*ppple)->sTrapBRegInfo.pvTrapWriteShadow )
                  [i] =
                  (pVDM( hvdm,
                         PBYTE,
                         (*ppple)->sTrapBRegInfo.pvTrapWriteShadow )
                     [i]
                   & pbData [i])
                  | (vvInput( INVALID_HVDM,
                              *ppple )
                     & ~ pbData [i]);

              }

#endif /* SVGA */

              /*
              ** Use vvShadowOutput since
              ** it handles reg. conditions
              */
              vvShadowOutput(
                hvdm,
                portIndx,
                portData,
                i,
                pVDM( hvdm,
                      PBYTE,
                      (*ppple)->                                /*          */
                        sTrapBRegInfo.pvTrapWriteShadow ) [i],  /*          */
                NULL,
                NULL,
                flCond );
#ifdef SVGA                                                     /*@V3.0YEE01*/
            }
#endif /* SVGA */                                               /*@V3.0YEE01*/
#else /* EGAVGA */

            /*
            ** On MONO/CGA cards,
            ** there are no conditions to worry about
            */
            OUTW( portIndx,
                  ((pVDM( hvdm,
                          PBYTE,
                          (*ppple)->sTrapBRegInfo               /*          */
                            .pvTrapWriteShadow)                 /*          */
                      [i] << 8) | i) );
#endif /* EGAVGA */
          }
        }
        else
        {
          /*
          ** The AUTOINC case (only used for DAC registers)
          */
          vvOutput( INVALID_HVDM,                               /*          */
                    (*ppple)->ppleBRegIndx,                     /*          */
                    0 );
          OUTSB( portData,
                 pVDM( hvdm,
                       PBYTE,
                       (*ppple)->                               /*          */
                         sTrapBRegInfo.pvTrapWriteShadow ),     /*          */
                 (*ppple)->ulBRegCount,
                 FALSE );
        }
        /*
        ** In ANY indexed case, don't forget to leave
        ** the index register at the last programmed value
        */
        /* ATC0 set by vvEnableDisplay() */

#ifdef EGAVGA                                                   /*          */
        if( (*ppple)->ppleBRegIndx != &pleATC0 )                /*          */
#endif /* EGAVGA */                                             /*          */
          vvOutput( INVALID_HVDM,                               /*          */
                    (*ppple)->ppleBRegIndx,                     /*          */
                    *pVDM( hvdm,
                           PBYTE,
                           (*ppple)->ppleBRegIndx->             /*          */
                             sTrapBRegInfo                      /*          */
                               .pvTrapWriteShadow ) );          /*          */
      }
    } /* end for ppple/if !PORTF_NOTRAP */                      /*          */

#ifdef   SVGA
  /*!!Please try NOT to add stuff here */                       /*          */
  /*!!unless it must be done last */                            /*          */
  /*!!We are trying to remove this section! */                  /*          */
  switch (ulSVGAAdapterType)
  {
    case  ATI_ADAPTER :                    /* see note above          */
      vvOutput( INVALID_HVDM,                                   /*          */
                &pleMiscOutWrite,                               /*          */
                pVDMData( hvdm )->regMiscOut );
      break;

    case  TRIDENT_ADAPTER :
      i = vvInput( INVALID_HVDM,                                /*          */
                   &pleSEQIndx );          /* restore reg defs*//*          */
      vvOutput( INVALID_HVDM,                                   /*          */
                &pleSEQIndx,                                    /*          */
                INDX_TRIDENT_REGDEF );
      if( pVDMData( hvdm )->VdmSVGA.stateTridentRegDef )
        vvInput( INVALID_HVDM,                                  /*          */
                 &pleSEQData );            /* set new */        /*          */
      else                                                      /*          */
        vvOutput( INVALID_HVDM,                                 /*          */
                  &pleSEQData,
                  0x01 );                  /* set old */        /*          */
      vvOutput( INVALID_HVDM,                                   /*          */
                &pleSEQIndx,
                (BYTE) i );
      break;
  }

#endif /* SVGA */

#ifdef   VGA
  ((PSVGAINFO) psCurAdapterInfo)->pfnVGADACRestore( hvdm );     /*          */
#endif /* VGA */

#ifdef   SVGA
  psCurAdapterInfo->pfnSVGARestoreIoState( hvdm );              /*          */
#endif /* SVGA */
}
#pragma  END_SWAP_CODE

