/*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 = VVMODE.C
 *
 * DESCRIPTIVE NAME = Virtual Video Int 10h SetMode Processing
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's Int 10h SetMode processing.
 *
 *
 * FUNCTIONS
 *              vvLoadCodePageFont()        Load current codepage font into VDM
 *              vvGetCodePageFont()         Return codepage font
 *              vvInt10Initialize()         Initialize the adapter via Int 10h
 *              vvInt10SetMode()            SetMode-initiation processing
 *              VVInt10SetModeReturn()      SetMode-return processing
 *
 * 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

extern ULONG flVVD;

#pragma  BEGIN_SWAP_DATA

extern PVOID pPhysVRAM;

extern PSCGAINFO psCurAdapterInfo;                              /*          */

#ifdef SVGA
extern ULONG ulSVGAAdapterType;                                 /*            */
extern PSACCELERATORINFO psCurAcceleratorInfo;                  /*          */
#endif /* SVGA */

#pragma  END_SWAP_DATA
#pragma  BEGIN_SWAP_CODE

#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvGetCodePageFont()
 *
 * DESCRIPTION   = Return codepage font
 *
 *                 This subroutine is called whenever an Int 10h subfunction
 *                 01h, 02h, 04h, 11h, 12h, 14h, 22h, 23h and 24h is called
 *                 with codepage enabled.
 *
 * INPUT         = None
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *                 FAILURE
 *                     FALSE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL PRIVENTRY vvGetCodePageFont(ULONG ulWidth,ULONG ulHeight,PBVDM pBuff)
{
  INT nbFont;                                    /*                         */
  PBYTE pbFont;                                  /*                         */


  if (!(nbFont = VDHGetCodePageFont(ulWidth,     /*                         */
                                    ulHeight,    /*                         */
                                    (PPVOID)SSToDS(&pbFont))))/*            */
    return  FALSE;                               /*                         */


  if (nbFont > PAGESIZE)     /* don't overflow font buffer                  */
    nbFont = PAGESIZE;                           /*                         */

  VDHCopyMem(pbFont,
             pBuff,
             nbFont);                            /*                         */

  VDHReleaseCodePageFont(pbFont);                /*                         */
  return  TRUE;                                  /*                         */
}                                                /*                         */
#endif                                           /* EGAVGA                  */

/***************************************************************************
 *
 * FUNCTION NAME = vvInt10Initialize()
 *
 * DESCRIPTION   = Initialize the adapter via Int 10h
 *
 *                 This subroutine initiates an Int 10h SetMode function
 *                 request for the current VDM.
 *
 * INPUT         = pcrf -> VDM register frame
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVSetFgndContext
 *
 ****************************************************************************/

VOID PRIVENTRY vvInt10Initialize(PCRF pcrf)
{

  /*
  ** Only the primary VVD should initialize; to correctly
  ** initialize a secondary adapter like MONO would require
  ** changing the equipment flags, and depending on the order in
  ** which the two VDDs are loaded, we might end up in the
  **       mode.  It's far better to leave any secondary display
  ** hardware alone until the session initializes it itself
  */

  if (flVVD&VVD_PRIMARY && !(VDMData.flVDMXVideo&VDMX_INT10INIT) && !(VDMData.flVDMVideo&VDM_IOINIT))
  {

    /*
    ** Issue INT 10h to set the default mode; we presume that
    ** the equipment flags are already set up to match rb_bVMode
    */

    VDHPushRegs(VDHREG_AX|VDHREG_BP);
    AH(pcrf) = INT10_SETMODE;
    AL(pcrf) = VDMBase.rb_bVMode;
    VDHPushInt(BIOSINT_VIDEO);
    VDMData.flVDMVideo &= ~VDM_IOINIT;
    VDMData.flVDMXVideo |= VDMX_INT10INIT;

#ifdef   EGAVGA

    /*
    ** But first, issue special Video Seven BIOS call to determine
    ** whether this is a Video Seven card (AX=6F00 returns BH='V',BL='7'
    */

    if (!((PVVSTRING)(VDMData.pInt10ReturnData))->vva_nChars)
    {
      VDHPushRegs(VDHREG_AX|VDHREG_BX);
      AX(pcrf) = 0x6F00;
      VDHPushInt(BIOSINT_VIDEO);
      ((PVVSTRING)(VDMData.pInt10ReturnData))->vva_nChars = -0x6F;
      VDHArmReturnHook(VDMData.hhookInt10Return,
                       VDHARH_NORMAL_IRET);
    }
#endif
  }
#ifdef SVGA                                     /*            */
  else if (VDMData.flVDMXVideo&VDMX_INT10RESTORE)
  {
     BYTE *pData; INT i;
     pData = &VDMBase.rb_bVMode;
     for (i=0;i<30;i++)
     {
        VDMData.VdmSVGA.abBiosData_1[i] = *pData;
        (BYTE *)pData++;
     } /* endfor */

     pData = &VDMBase.rb_nVRows;
     for (i=0;i<7;i++)
     {
        VDMData.VdmSVGA.abBiosData_2[i] = *pData;
        (BYTE *)pData++;
     } /* endfor */

     VDMData.flVDMX2Video  |= VDMX2_IGNOREINT10;
     /*
     **            Instead of using kernel services VDHPushRegs and VDHPopRegs,
     ** which in some instances caused corruption of the PCRF_SP, I'll save
     ** used registers in our instance and restore them following the injected
     ** mode return in the vvSVGARestoreModeReturn
     */
//               VDHPushRegs(VDHREG_AX|VDHREG_BX);
     VDMData.VdmSVGA.regAXSave = AX(pcrf);
     VDMData.VdmSVGA.regBXSave = BX(pcrf);
     if (VDMData.ulBIOSMode > 0x100)
     {
       AX(pcrf) = 0x4f02;
       BX(pcrf) = VDMData.ulBIOSMode;
     }
     else if (ulSVGAAdapterType != VIDEO7_ADAPTER)
     {
       AH(pcrf) = INT10_SETMODE;
       AL(pcrf) = (BYTE) VDMData.ulBIOSMode;
     }
     else
     {
       AX(pcrf) = 0x6f05;
       BL(pcrf) = (BYTE) VDMData.ulBIOSMode;
     }
     VDHPushInt(BIOSINT_VIDEO);
  }
#endif
}

#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvLoadCodePageFont()
 *
 * DESCRIPTION   = Load current codepage font into VDM
 *
 *
 * INPUT         = None
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *                 FAILURE
 *                     FALSE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvInt10SetModeReturn & ...
 *
 ****************************************************************************/

BOOL PRIVENTRY vvLoadCodePageFont()
{
  INT nbFont;
  PBYTE pbFont;
  register INT i;
  register PBYTE pbSrc,pbDest;
  MSTATE tempState;                              /*                         */
  ULONG ulCellWidth,ulCellHeight;                /*                         */
  ULONG uMode;                                   /*                         */

  /*
  ** ignore VM BOOT guys                                                 
  */

  if (VDMData.flVDMX2Video&VDMX2_V86MACHINE)            /*          */
    return  TRUE;

  uMode = VDMBase.rb_bVMode;                     /*                         */

  if (uMode <= BIOSVMODE_CO80 || uMode == BIOSVMODE_MONO80)
  {                                              /*                         */
    nbFont = VDHGetCodePageFont(VDMData.PtrData.vmssVideo.vmss_ulCellWidth,
                                VDMData.PtrData.vmssVideo.vmss_ulCellHeight,
                                (PPVOID)SSToDS(&pbFont));

    if (!nbFont)
      return  FALSE;

    /*
    ** if foreground, transfer font to physical VRAM
    */

    if (VDMData.flVDMVideo&VDM_FGND)
    {
      pbDest = pPhysVRAM;
      tempState = VDMData.mstateCopy;            /*                         */
      VDMData.mstateCopy = MEMORY_NONE;          /* force change            */
      vvSetCopyState( CURRENT_VDM,
                      MEMORY_FONT,
                      PLANE2 );
    }

    /*
    ** otherwise, transfer font to the "virtual" plane 2
    */

    else
    {

      if (VDMData.anpgPlane[BANK0][PLANE2] < 2)
        vvGrowPlane(CURRENT_VDM,
                    PLANE2,
                    2,
                    BANK0);                      /*                         */
      pbDest = VDMData.apPlane[BANK0][PLANE2];
    }
    pbSrc = pbFont;

    if (nbFont > PAGESIZE *2)
      nbFont = PAGESIZE *2;

    /*
    **           
    ** Mark font plane pages as such in the aapstate when
    ** loading the codepage font. This is required especially on
    ** Tridents, which if the previous mode left A0000 enabled will
    ** load the font plane before it sets its IO state. So, when
    ** GDC mode register is touched to set the mode, the font pages
    ** are invalidated and lost.
    */
    if (VDMData.mstateVideo == MEMORY_TEXT)     /*                          */
    {
      for(i=0;i<2;i++)
      {
        if((VDMData.aapstate[BANK0][i][PLANE2]&PAGE_VALID) != PAGE_FONT)
        {
          VDMData.aapstate[BANK0][i][PLANE2] &= ~PAGE_TYPE;
          VDMData.aapstate[BANK0][i][PLANE2] |= PAGE_FONT;
        }
      }
    }

    while (nbFont > 0)
    {

      for (i = 0; i < VDMData.PtrData.vmssVideo.vmss_ulCellHeight; i++,
           nbFont--)
        *pbDest++ = *pbSrc++;

      for (; i < 32; i++)
        *pbDest++ = 0;
    }

    if (VDMData.flVDMVideo&VDM_FGND)
    {                                            /*                         */
      vvRestoreCopyState(CURRENT_VDM,
                         SETIO_SHADOWED);
      VDMData.mstateCopy = tempState;            /*                         */
    }                                            /*                         */
  }

  else
  {                                              /*                         */

    switch (uMode)
    {                                    /*                                 */
      case  BIOSVMODE_CO320X200X4 :      /* BIOS mode 4                     */
      case  BIOSVMODE_BW320X200X4 :      /* BIOS mode 5                     */
      case  BIOSVMODE_CO640X200X2 :      /* BIOS mode 6                     */
      case  BIOSVMODE_CO320X200X16 :     /* BIOS mode D                     */
      case  BIOSVMODE_CO640X200X16 :     /* BIOS mode E                     */
      case  BIOSVMODE_CO320X200X256 :    /* BIOS mode 13                    */
        ulCellHeight = 8;                /* use 8x8 font                    */
        break;                           /*                                 */
      case  BIOSVMODE_MONO640X350X4 :    /* BIOS mode F                     */
      case  BIOSVMODE_CO640X350X16 :     /* BIOS mode 10                    */
        ulCellHeight = 14;               /* use 8x14 font                   */
        break;                           /*                                 */
      case  BIOSVMODE_CO640X480X2 :      /* BIOS mode 11                    */
      case  BIOSVMODE_CO640X480X16 :     /* BIOS mode 12                    */
        ulCellHeight = 16;               /* use 8x16 font                   */
        break;                           /*                                 */
      default  :                         /* no op anything else             */
        return  FALSE;                   /*                                 */
    }                                    /*                                 */

    ulCellWidth = 8;                     /* set default width               */

    /*
    ** read bitmap font from VIOTBL.DCP                                     
    */

    if (!(nbFont = VDHGetCodePageFont(ulCellWidth, /*                       */
                                      ulCellHeight,
                                      (PPVOID)SSToDS(&pbFont))))
      return  FALSE;


    if (nbFont > PAGESIZE)                  /* don't go beyond 4K           */
      nbFont = PAGESIZE;

    /*
    ** transfer font image from system memory into VDM                      
    */

    VDHCopyMem(pbFont,
               VDMData.pCPBuff,
               nbFont);                          /*                         */

    /*
    ** don't replace INT 1F if owner is neither us or ROM                   
    */
 /*                                                                         
  * if (SEGMENTOF16(VDMBase.rb_avpIVT[BIOSINT_VIDEOGRAPH]) == HISEG
  *    (VDMData.pCPBuff) || (SEGMENTOF16(VDMBase.rb_avpIVT[BIOSINT_VIDEOGRAPH]
  *    ) == VDMData.ROMint1fSeg))
  *   VDMBase.rb_avpIVT[BIOSINT_VIDEOGRAPH] = VPFROMVADDR(HISEG
  *      (VDMData.pCPBuff),
  *                                                       (LOOFF
  *                                                       (VDMData.pCPBuff)+
  *                                                       (ulCellHeight *128))
  *      );
  */
    /*
    ** replace INT 43 with the new font buffer                              
    */

    VDMBase.rb_avpIVT[0x43] = VPFROMVADDR(HISEG(VDMData.pCPBuff),
                                          LOOFF(VDMData.pCPBuff));
  }                                              /*                         */
  VDHReleaseCodePageFont(pbFont);
  return  TRUE;
}

#endif                                           /* EGAVGA                  */

/***************************************************************************
 *
 * FUNCTION NAME = vvInt10SetMode()
 *
 * DESCRIPTION   = SetMode-initiation processing
 *
 *                 This subroutine is called directly from the actual Int 10h
 *                 hook for the SetMode case only, and takes care of hooking
 *                 the return from the SetMode call and notifying the mouse
 *                 of the new mode being set.
 *
 * INPUT         = pcrf -> VDM register frame
 *
 * OUTPUT        = EMULATED
 *                     TRUE
 *                 NOT EMULATED
 *                     FALSE (pass control to next VDD and/or ROM)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 deactivate pointer
 *                 disable pointer drawing for duration
 *                 hook return from Int 10h call
 *
 ****************************************************************************/

BOOL HOOKENTRY vvInt10SetMode(register PCRF pcrf)
{
  USHORT iretFrame[3];
  USHORT modeMax = 0xFFFF;                       /*                         */
  USHORT usNewMode;                              /*                         */
  ULONG ulEquip = VDMBase.rb_fsEquip&BIOSEQUIP_VIDEOMASK;

  usNewMode =
    psCurAdapterInfo->pusfnCGAPrepareSetMode( CURRENT_VDM,      /*          */
                                              pcrf );

#ifdef   VDDDEBUGALL
  PRINTDEBUG("New video mode: %02xh\n",
             usNewMode);
#endif

#ifdef   PROPERTIES

  if (VDMData.flVDMXVideo&VDMX_CGARESTRICT)
  {

    /*
    ** If caller changed equipment flags, coerce to color
    */

    if (!(VDMData.flVDMXVideo&VDMX_MONORESTRICT) && ulEquip ==
       BIOSEQUIP_MONOVIDEO)
    {
      VDMBase.rb_fsEquip &= ~BIOSEQUIP_VIDEOMASK;
      VDMBase.rb_fsEquip |= (ulEquip = BIOSEQUIP_COLOR80VIDEO);
    }
    modeMax = BIOSVMODE_CO640X200X2;
  }

  if (VDMData.flVDMXVideo&VDMX_MONORESTRICT)
    modeMax = BIOSVMODE_MONO80;

  /*
  ** Ignore the mode change if it has been restricted
  */

  if (usNewMode > modeMax)
    return  TRUE;
#endif

#ifdef   MONO

  if (ulEquip == BIOSEQUIP_MONOVIDEO)
  {

    if (usNewMode == BIOSVMODE_MONO80)
      VDMData.flVDMXVideo |= VDMX_ACTIVE;
  }

  else
  {

    if (usNewMode != BIOSVMODE_MONO80)
      VDMData.flVDMXVideo &= ~VDMX_ACTIVE;
  }

#else

  if (flVVD&VVD_MONOPRESENT)
  {

    if (ulEquip == BIOSEQUIP_MONOVIDEO)
    {

      if (usNewMode == BIOSVMODE_MONO80)
        VDMData.flVDMXVideo &= ~VDMX_ACTIVE;
    }

    else
    {

      if (usNewMode != BIOSVMODE_MONO80)
        VDMData.flVDMXVideo |= VDMX_ACTIVE;
    }
  }
#endif

  /*
  ** If not the active display, lie low (like the ROM)
  */

  if (!(VDMData.flVDMXVideo&VDMX_ACTIVE))
    return  FALSE;

  /*
  ** Deactivate pointer, and disable further pointer drawing
  */

  VVHidePtr(CURRENT_VDM);
  VDMData.PtrData.fPtrFrozenVideo++;
  VDMData.ulBIOSMode = usNewMode;
  VDMData.flVDMVideo |= VDM_MODECHANGING;

  /*
  ** Now that the MODECHANGING bit is set, if we're doing CGA/MONO
  ** restriction, this is the time to fix up all the mappings in the
  ** video address range, so that the ROM will not stomp on user data
  */

  if (VDMData.flVDMXVideo&(VDMX_CGARESTRICT|VDMX_MONORESTRICT))
  {

    /*
    ** Switch stacks first
    */

    VDHPopStack(sizeof(iretFrame),
                SSToDS(&iretFrame));
    VDMData.vpOldStack = VPFROMVADDR(SS(pcrf),
                                     SP(pcrf));
    SS(pcrf) = LOSEG(VDMData.pvdmAltStack);
    SP(pcrf) = HIOFF(VDMData.pvdmAltStack);
    VDHPushStack(sizeof(iretFrame),
                 SSToDS(&iretFrame));
  }

#ifdef SVGA                                                     /*            */
  if ((VDMData.flVDMXVideo & VDMX_INT10RESTORE) && (VDMData.flVDMX2Video & VDMX2_IGNOREINT10))
     VDHArmReturnHook(VDMData.hhookRestoreModeReturn,
                   VDHARH_RECURSIVE_IRET);
  else
  {
#endif
    /*
    ** Force trapping on retrace port
    */

    if (!(VDMData.flVDMXVideo&VDMX_RTRCEMULATE))
    {
      VDMData.flVDMXVideo |= (VDMX_RTRCOVERRIDE|VDMX_RTRCEMULATE);
      VVSpecialCaseIO( NULL,
                     NULL );
    }
    /*
    ** FLAG: 20-Apr-90
    **
    ** This EnableBuffer call is simply one of many possible ways to
    ** fix the following *kind* of problem:  Application is graphics mode,
    ** buffer enabled at A0000h, then switches to text mode by first loading
    ** the font at A0000h (which we miss because those pages are still
    ** enabled), then initializing the buffer at B8000h (which we *do* see).
    ** I prefer to not rely on INT 10h to catch the start of these sorts
    ** of transitions, but in this case, it's so cheap and compatible
    ** (and the full solution is so much more work), that I've given in.
    */
    VVEnableBuffer(FALSE,
                 pcrf);
    VDHArmReturnHook(VDMData.hhookInt10SetModeReturn,
                   VDHARH_RECURSIVE_IRET);
#ifdef SVGA                                                     /*            */
  }
#endif                                                          /*            */
  VDMData.nInt10Setmode++;                                     /*            */
  return  FALSE;
}

/***************************************************************************
 *
 * FUNCTION NAME = VVInt10SetModeReturn()
 *
 * DESCRIPTION   = SetMode-return processing
 *
 *                 This subroutine is called whenever an Int 10h SetMode
 *                 completes.  Its primary purpose is to notify the virtual
 *                 mouse driver of the new video mode, and reload the default
 *                 code page font if the VDM has entered/remained in a text
 *                 mode.
 *
 * INPUT         = p - (ignored)
 *                 pcrf -> VDM register frame (ignored)
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 notify virtual mouse of screen/cell sizes
 *                 allow pointer drawing again
 *                 check for codepage font
 *                 if font exists
 *                   if foreground VDM
 *                     set copy state
 *                     copy font data into VRAM
 *                     restore copy state
 *                   else
 *                     copy font data directly into PLANE2 buffer
 *                   release font
 *
 ****************************************************************************/

VOID HOOKENTRY VVInt10SetModeReturn(PVOID p,PCRF pcrf)
{
  PBYTE pbFont;
  ULONG nbFont;
  USHORT iretFrame[3];
#ifdef   SVGA
  ULONG mstateVideo;                                            /*          */
#endif

  RequestMutexSem(VDMData.hmxVideoState);                       /*          */

#ifdef   SVGA
  vvSVGAFixSetMode( CURRENT_VDM );                              /*          */
#endif /* SVGA */
  /* RequestMutexSem(VDMData.hmxVideoState); Move earlier */    /*          */

  if (VDMData.flVDMXVideo&(VDMX_CGARESTRICT|VDMX_MONORESTRICT))
  {

    /*
    ** Now switch stacks *back*
    */

    SS(pcrf) = WORDOF(VDMData.vpOldStack,
                      1);
    SP(pcrf) = WORDOF(VDMData.vpOldStack,
                      0);
  }

  VDMData.nInt10Setmode--;                                      /*            */

  /*
  ** If we initiated the SetMode, then restore user registers
  */

  if (VDMData.flVDMXVideo&VDMX_INT10INIT)
    if (!VDMData.nInt10Setmode)                                 /*            */
    {                                                           /*            */
      VDMData.flVDMXVideo &= ~VDMX_INT10INIT;
      VDHPopRegs(VDHREG_AX|VDHREG_BP);
    }                                                           /*            */

  /*
  ** Remove trapping enforcement on retrace port
  */

  if (VDMData.flVDMXVideo&VDMX_RTRCOVERRIDE)
    VDMData.flVDMXVideo &= ~(VDMX_RTRCOVERRIDE|VDMX_RTRCEMULATE);

#ifdef   SVGA
  mstateVideo = VDMData.mstateVideo;                            /*          */
#endif
  /*
  ** Get new state info,
  ** now that I/O initialization and fixups are complete
  */

  VDMData.flVDMVideo |= VDM_IOINIT;
  VDMData.flVDMVideo &= ~VDM_STATEINIT;
  vvUpdateAll(CURRENT_VDM,
              TRUE);

#ifdef SVGA                                                     /*          */
  /*
  ** This is an attempt to handle the situation where the previous mode
  ** was 256-color and is changing to 16-color. BIOS clears VRAM while
  ** in 256-color mode, page states are therefore not updated appropriately
  ** when faults occur. So we invalidate the mappings here and take faults
  ** again in the correct mode. The converse also happens but page states
  ** are not required in 256-color modes and therefore do not interfere
  ** with the save/restore of VRAM.
  */

  if ((mstateVideo == MEMORY_GRFX256) &&
      (VDMData.mstateVideo == MEMORY_GRFX))
  {
    VVEnableBuffer(FALSE,
                   pcrf);
  }
#endif /* SVGA */

  /*
  ** This should also be a good time to shrink the virtual buffer
  */

  if (!(VDMData.flVDMVideo&VDM_FGND))
    vvShrinkBuffer(CURRENT_VDM,
                   FALSE);

  /*
  ** Allow pointer drawing again;
  ** by this time, the virtual mouse will have disabled itself
  */

  VDMData.PtrData.fPtrFrozenVideo--;
  AssertTRUE(VDMData.PtrData.fPtrFrozenVideo >= 0);
  VDMData.flVDMVideo &= ~VDM_MODECHANGING;

  /*
  ** Now that the MODECHANGING bit is clear, if we're doing CGA/MONO
  ** restriction, this is the time to fix up all the mappings in the
  ** video address range, so that the VDM will not stomp on font data
  */

  if (VDMData.flVDMXVideo&(VDMX_CGARESTRICT|VDMX_MONORESTRICT))
    VVEnableBuffer(TRUE,
                   pcrf);

  /*
  ** Have to release VDMState semaphore before adding/flushing events
  */

  ReleaseMutexSem(VDMData.hmxVideoState);

  /*
  ** If mode events were posted to the Shield, flush them now
  */

  vvFlushEvent(CURRENT_VDM,
               VVDEVENT_MODE,
               0);
  vvFlushEvent(CURRENT_VDM,
               VVDEVENT_LVB,
               0);

#ifdef   EGAVGA

  /*
  ** Get the current (ie, new) video mode from the BIOS data area
  */

  if (VDMData.vvMode.vvm_cpID != 0)              /*                         */
    vvLoadCodePageFont();
#endif                                           /* EGAVGA                  */

#ifdef   SVGA
  if( (((VDMBase.rb_bVMode & ~BIOSVINFO_DONTCLEAR) > 0x13)
       && (VDMData.flVDMVideo & VDM_WINDOWED)
       && (VDMData.mstateVideo > MEMORY_TEXT))
      || ((VDMData.flVDMXVideo & VDMX_ENHANCEDMODE)             /*          */
          && !(VDMData.flVDMVideo & VDM_FGND)) )                /*          */
  {
    if (!vdhBTS(&VDMData.flVDMVideo,
                LOG2(VDM_FROZEN)))
      VDHFreezeVDM(CURRENT_VDM);
    vvAddEvent(CURRENT_VDM,
               VVDEVENT_MODE,
               NULL,
               0);
  }
#endif /* SVGA */
}
#pragma  END_SWAP_CODE

