/*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 = VVPORT.C
 *
 * DESCRIPTIVE NAME = Virtual Video Port Management
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's routines to install, remove,
 *              and otherwise generally tend to I/O hooks.
 *
 * FUNCTIONS    vvSetIOHooks()         Install/remove I/O hooks
 *              vvEnableIO()           Enable I/O
 *              VVSpecialCaseIO()      Enable/disable special-case I/O
 *                                     according to state
 *              vvAdjustedPort()       Adjust given port # for current state
 *              vvQueryLatchAddress()  Determine suitable latch addres
 *              vvSaveLatches()        Save physical latch contents
 *              vvRestoreLatches()     Restore physical latch contents
 *              vvRestoreDACState()    Restore DAC state to hardware
 *              vvDisableDisplay(hvdm) Disable display
 *              vvEnableDisplay()      Enable display
 *              VVForceDisplay()       Force display on (for VKBD)
 *              vvDisableVRAM()        Disable VRAM thru Misc. Output
 *
 * 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 HLE ahleFgnd[];
extern PBYTE pPhysVRAM;
extern PBYTE pvdmPhysVRAM;

#ifdef   EGAVGA
extern HMXSEM hmxPhysLatch;
extern PBYTE pbSEQExtShadowIndx;
extern PRLE prleSEQExtShadowData[MAX_SEQREGS];
extern PBYTE pbGDCExtShadowIndx;
extern PRLE prleGDCExtShadowData[MAX_GDCREGS];
#endif

#ifdef   SVGA
extern ULONG ulSVGAAdapterType;
extern ULONG ulXGAInstance;
extern ULONG ulSVGADACFamily;            /*            */
#endif
#pragma  END_SWAP_DATA

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

/***************************************************************************
 *
 * FUNCTION NAME = vvSetIOHooks()
 *
 * DESCRIPTION   = Install/remove I/O hooks
 *
 *                 This routine walks through the appropriate I/O port list,
 *                 either installing or removing the set of hooks for every
 *                 I/O port listed.  The appropriate I/O list is determined
 *                 by the current session state.
 *
 * INPUT         = phle     -> list of I/O hooks to install
 *                 fInstall == TRUE to install, FALSE to remove
 *                 fWait    == TRUE to wait if out of memory, FALSE to return error
 *
 * OUTPUT        = TRUE if hooks installed, FALSE if error
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL PRIVENTRY vvSetIOHooks(register PHLE phle,BOOL fInstall,BOOL fWait)
{
  PORT port;
  INT nHooks;
  FLAGS flOpt;
  register INT i;

  if ((phle == (PHLE)ahleFgnd) &&                               /*            */
      (VDMData.flVDMXVideo & VDMX_NOIOTRAPPING))                /*            */
    return TRUE;                                                /*            */

  /*
  ** Walk the hook-list of ports-and-hooks
  */

  while (phle->hle_port != HLE_ENDPORT)
  {

    /*
    ** Fill in private IOH from hook-list entry data
    */

    i = 0;

    while (i < 5 && phle->hle_pfn[i] != HLE_END)
    {
      PFNOF(VDMData.iohVideo,
            i) = phle->hle_pfn[i];
      i++;
    }

    /*
    ** Save # of hooks for this hook-list entry
    */

    nHooks = i;

    /*
    ** Zero out the rest of the private IOH
    */

    while (i < 5)
      PFNOF(VDMData.iohVideo,
            i++) = NULL;

    /*
    ** Determine the hook-type
    */

    flOpt = 0;

    if (!(phle->hle_port&PORTF_CHOOK))
      flOpt |= VDHIIH_ASM_HOOK;

    if (nHooks > 2)
      flOpt |= VDHIIH_NO_SIMULATE;

    /*
    ** Install/remove the hook
    */

    port = phle->hle_port&PORT_MASK;

#ifdef   EGAVGA /* Install these ports only within the VMONO driver */

    if (!((flVVD&VVD_MONOPRESENT) && (port == PORT_MONOCRTINDX || port ==
       PORT_MONOCRTDATA || port == PORT_MONOSTATUS1)))
#endif

#ifdef   SVGA /* do specifics for IBM SVGA */

      if ((ulSVGAAdapterType == IBM_ADAPTER) && (port == ulXGAInstance))
      {

        for (; (port & 0x0f) < AXGA_TOTAL-1; port++)            /*            */

          if ((port & 0x0f) != AXGA_APERTURE_CONTROL)           /*            */

            if (fInstall)
            {

              while (!VDHInstallIOHook(CURRENT_VDM,
                                       port,
                                       1,
                                       &VDMData.iohVideo,
                                       flOpt))

                if (!fWait || !vvFreezeVDM(CURRENT_VDM,
                                           TRUE))
                  return  FALSE;
            }

            else

              VDHRemoveIOHook(CURRENT_VDM,
                              port,
                              1,
                              &VDMData.iohVideo);
      }

      else
#endif                                           /* end IBM SVGA specifics  */

        if (fInstall)
        {

          while (!VDHInstallIOHook(CURRENT_VDM,
                                   port,
                                   1,
                                   &VDMData.iohVideo,
                                   flOpt))
          {

            if (!fWait || !vvFreezeVDM(CURRENT_VDM,
                                       TRUE))
              return  FALSE;
          }

          if ( (VDMData.flVDMXVideo & VDMX_NOIOTRAPPING) &&     /*            */
              !(flOpt & VDHIIH_ALWAYS_TRAP) )
          {

              /*
              ** Re-enable - VDHInstallIOHook() should do this.
              */

              VDHSetIOHookState(CURRENT_VDM,
                                port,
                                1,
                                &VDMData.iohVideo,
                                SETIO_TRAP);
          }
        }

        else
        {
          VDHRemoveIOHook(CURRENT_VDM,
                          port,
                          1,
                          &VDMData.iohVideo);
        }

    /*
    ** Advance to next variable-length hook-list entry,
    ** allowing for the port # and terminating value as well
    */

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

#ifdef   VGA

  /*
  ** Re-installing/de-installing hooks always re-enables trapping
  */

  VDMData.flVDMVideo |= (VDM_MOTIONTRAP|VDM_SPECIALTRAP);
#endif
  VDMData.flVDMXVideo |= VDMX_RTRCTRAP;
  return  TRUE;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvEnableIO()
 *
 * DESCRIPTION   = Enable I/O
 *
 *                 This routine walks through the foreground I/O hook list,
 *                 enabling VDM I/O access for every I/O port so privileged
 *                 (flagged PORTF_NOTRAP).  It is assumed that all ports are
 *                 currently being trapped by default.
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvEnableIO()
{
  register INT i;
  register PHLE phle;
  PORT port;

  if (VDMData.flVDMXVideo & VDMX_NOIOTRAPPING)                  /*            */
    return;                                                     /*            */

  /*
  ** Walk the foreground hook list
  */

  phle = ahleFgnd;

  while (phle->hle_port != HLE_ENDPORT)
  {

    /*
    ** If don't want trapping, or no hook defined
    */

    if ((phle->hle_port&PORTF_NOTRAP) || phle->hle_pfn[0] == HLE_END)
    {

      /*
      ** Install/remove the hook
      */

      port = phle->hle_port&PORT_MASK;

#ifdef   EGAVGA /* These ports installed only within the VMONO driver */

      if (!((flVVD&VVD_MONOPRESENT) && (port == PORT_MONOCRTINDX || port ==
         PORT_MONOCRTDATA || port == PORT_MONOSTATUS1)))
#endif

              /*
              ** Then undo the default state (trapping enabled)
              */

              VDHSetIOHookState(CURRENT_VDM,
                                phle->hle_port&PORT_MASK,
                                1,
                                &VDMData.iohVideo,
                                SETIO_NOTRAP);
    }

    /*
    ** Scan for the end of this hook-list entry
    */

    i = 0;

    while (i < 5 && phle->hle_pfn[i] != HLE_END)
      ++i;

    /*
    ** Advance to the next variable-length hook-list entry,
    ** allowing for the port # and terminating value as well
    */

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

#ifdef   VGA
  VDMData.flVDMVideo &= ~(VDM_MOTIONTRAP|VDM_SPECIALTRAP);
#endif
  VVSpecialCaseIO(NULL,
                  NULL);
}

/***************************************************************************
 *
 * FUNCTION NAME = VVSpecialCaseIO()
 *
 * DESCRIPTION   = Enable/disable special-case I/O according to state
 *
 *
 * INPUT         = hhook == hook handle (NULL if none)
 *                 pcrf  -> VDM register frame (NULL if called from VDD)
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID EXPENTRY VVSpecialCaseIO(HHOOK hhook,PCRF pcrf)
{
  INT i;
  BOOL fTrap;

#ifdef   VGA
  static PORT ports[] =
  {
    PORT_SEQINDX,PORT_SEQDATA,PORT_GDCINDX,PORT_GDCDATA
  }
  ;

  if (VDMData.flVDMXVideo & VDMX_NOIOTRAPPING)                  /*            */
    return;                                                     /*            */

  fTrap = (VDMData.mstateVideo <= MEMORY_FONT);

#ifdef  VTEXT                                                           //J-TS00V
  if ((VDMData.GaleData.flVtext & VDMV_VTEXT_INSTALLED) &&              //J-TS00V
      (VDMData.GaleData.flVtext & VDMV_SUPPORTED_TEXT_MODE))            //J-TS00V
      fTrap = (MEMORY_GRFX <= MEMORY_FONT);                             //J-TS00V
#endif  //VTEXT                                                         //J-TS00V

  if (fTrap != TESTBIT(VDMData.flVDMVideo,
                       VDM_SPECIALTRAP))
  {
    SETBIT(VDMData.flVDMVideo,
           VDM_SPECIALTRAP,
           fTrap);

    if (VDMData.flVDMVideo&VDM_FGND)

      for (i = 0; i < NElements(ports); i++)
        VDHSetIOHookState(CURRENT_VDM,
                          ports[i],
                          1,
                          &VDMData.iohVideo,
                          fTrap);
  }
  fTrap = TESTBIT(VDMData.flVDMVideo,
                  VDM_UNKNOWNFAULT);

  if (fTrap != TESTBIT(VDMData.flVDMVideo,
                       VDM_MOTIONTRAP))
  {
    SETBIT(VDMData.flVDMVideo,
           VDM_MOTIONTRAP,
           fTrap);

    if (VDMData.flVDMVideo&VDM_FGND)

      /*
      ** Note the 2: only fiddle with GDC ports for this case
      */

      for (i = 2; i < NElements(ports); i++)
        VDHSetIOHookState(CURRENT_VDM,
                          ports[i],
                          1,
                          &VDMData.iohVideo,
                          fTrap);
  }
#endif
  fTrap = TESTBIT(VDMData.flVDMXVideo,
                  VDMX_RTRCEMULATE);

  if (fTrap != TESTBIT(VDMData.flVDMXVideo,
                       VDMX_RTRCTRAP))
  {
    SETBIT(VDMData.flVDMXVideo,
           VDMX_RTRCTRAP,
           fTrap);

/* #ifdef FGND_ONLY                                                         */

    if (VDMData.flVDMVideo&VDM_FGND)
    {

/* #endif                                                                   */

#ifdef   CGA
      i = PORT_COLRSTATUS1;

#else
      i = PORT_MONOSTATUS1;
#endif

#ifdef   EGAVGA

      if (VDMData.regMiscOut&MISCOUT_COLRPORTS)
        i = PORT_COLRSTATUS1;
#endif
      VDHSetIOHookState(CURRENT_VDM,
                        i,
                        1,
                        &VDMData.iohVideo,
                        fTrap);

/* #ifdef FGND_ONLY                                                         */

    }

/* #endif                                                                   */

  }

  if (hhook)
    FREEHOOK(hhook);
}

/***************************************************************************
 *
 * FUNCTION NAME = vvAdjustedPort()
 *
 * DESCRIPTION   = Adjust given port # for current state
 *
 *                 Strips off flags attached to port #, if any, and adjusts
 *                 the value of the port, if necessary.
 *
 * INPUT         = hvdm -> VDM
 *                 port == port #
 *
 * OUTPUT        = port (possibly unchanged)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

PORT PRIVENTRY vvAdjustedPort(HVDM hvdm,PORT port)
{

#ifdef   EGAVGA

  if (port&PORTF_COLRMONO)

    if (!(pVDMData(hvdm)->regMiscOut&MISCOUT_COLRPORTS))
      port -= 0x20;
#endif                                           /* EGAVGA                  */
return (port&PORT_MASK);
}

#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvQueryLatchAddress()
 *
 * DESCRIPTION   = Determine suitable latch addres
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = pbPhysLatch -> latch suitable for specified VDM, NULL if none
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

PBYTE PRIVENTRY vvQueryLatchAddress(HVDM hvdm)
{
  register PVDMDATA pvd = pVDMData(hvdm);


  if (pvd->flVDMVideo&VDM_PHYSPAGE)
    return  pPhysVRAM+vvdrqVideo.vvd_offLatchByte;

  else

    if (pvd->flVDMVideo&VDM_FGND)

      return  pPhysVRAM+(pvd->pvdmPhysVRAMActive-pvdmPhysVRAM)+
         (pvd->npgPhysVRAMActive *PAGESIZE)-1;

    else
      return  NULL;
}

#endif

#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvSaveLatches()
 *
 * DESCRIPTION   = Save physical latch contents
 *
 *                 Save the physical latch state.  The latch values are
 *                 transferred to physical memory, and then copied from
 *                 there to virtual storage.
 *
 * INPUT         = hvdm -> VDM
 *                 fGlobal == TRUE to save in global storage,
 *                            FALSE in per-VDM storage
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvSaveLatches(HVDM hvdm,BOOL fGlobal)
{
  register INT i;
  register PBYTE pbPhysLatch;
  register PVDMDATA pvd = pVDMData(hvdm);


#ifdef  VTEXT                                                           //J-TS00V
  if (((pvd->mstateVideo == MEMORY_GRFX) ||                             //J-TS00V
       ((pvd->GaleData.flVtext & VDMV_VTEXT_INSTALLED) &&               //J-TS00V
        (pvd->GaleData.flVtext & VDMV_SUPPORTED_TEXT_MODE))) &&         //J-TS00V
      (pbPhysLatch = vvQueryLatchAddress(hvdm)))                        //J-TS00V
#else   //VTEXT                                                         //J-TS00V
  if (pvd->mstateVideo == MEMORY_GRFX && (pbPhysLatch = vvQueryLatchAddress
     (hvdm)))
#endif  //VTEXT                                                         //J-TS00V
  {

    /*
    ** We have to take this semaphore because saving
    ** the latches requires using a global VRAM location
    */

    RequestMutexSem(hmxPhysLatch);
    vvSetCopyState(hvdm,
                   MEMORY_NONE,
                   ALL_PLANES);
    *pbPhysLatch = 0;            /* a dummy write, to save latches */

    if (!fGlobal)
    {

      for (i = 0; i < MAX_PLANES; i++)
      {
        vvSetCopyState(hvdm,
                       MEMORY_GRFX,
                       i);
        pvd->bLatches[i] = *pbPhysLatch;
      }

      /*
      ** Yes, we only release this semaphore on non-global saves
      */

      ReleaseMutexSem(hmxPhysLatch);
    }
  }
}

#endif

#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvRestoreLatches()
 *
 * DESCRIPTION   = Restore physical latch contents
 *
 *                 Restore the physical latch state.  The latch values are
 *                 copied from virtual storage to the physical memory, and
 *                 then loaded into the physical latches.
 *
 * INPUT         = hvdm -> VDM
 *                 fGlobal == TRUE to restore from global storage, FALSE from per-VDM storage
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvRestoreLatches(HVDM hvdm,BOOL fGlobal)
{
  register INT i;
  register PBYTE pbPhysLatch;
  register PVDMDATA pvd = pVDMData(hvdm);


#ifdef  VTEXT                                                           //J-TS00V
  if (((pvd->mstateVideo == MEMORY_GRFX) ||                             //J-TS00V
       ((pvd->GaleData.flVtext & VDMV_VTEXT_INSTALLED) &&               //J-TS00V
        (pvd->GaleData.flVtext & VDMV_SUPPORTED_TEXT_MODE))) &&         //J-TS00V
      (pbPhysLatch = vvQueryLatchAddress(hvdm)))                        //J-TS00V
#else   //VTEXT                                                         //J-TS00V
  if (pvd->mstateVideo == MEMORY_GRFX && (pbPhysLatch = vvQueryLatchAddress
     (hvdm)))
#endif  //VTEXT                                                         //J-TS00V
  {

    if (!fGlobal)
    {

      /*
      ** We have to take this semaphore because saving
      ** the latches requires using a global VRAM location
      */

      RequestMutexSem(hmxPhysLatch);

      for (i = 0; i < MAX_PLANES; i++)
      {
        vvSetCopyState(hvdm,
                       MEMORY_GRFX,
                       i);
        *pbPhysLatch = pvd->bLatches[i];
      }
    }
    i = *pbPhysLatch;                    /* a dummy read, to load latches */
    ReleaseMutexSem(hmxPhysLatch);
  }
}

#endif

#ifdef   VGA

/***************************************************************************
 *
 * FUNCTION NAME = vvSaveDACState()                                       
 *
 * DESCRIPTION   = Save DAC state from hardware
 *
 *                 Save the DAC's internal state.  Specifically, this is:
 *                     - Read/Write mode
 *                     - 0 (normal), 1 or 2 bytes read/written
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvSaveDACState(HVDM hvdm)
{
  INT n;
  BYTE bIndx;                                                   /*          */
  register INT i;
  register PVDMDATA pvd = pVDMData(hvdm);
  register PBYTE pbDACData;

  if (pvd->flVDMXVideo & VDMX_NOIOTRAPPING)
  {
    pvd->regDACIndx = INB(PORT_VGADACWRITE);
    pvd->stateDAC = INB(PORT_VGADACREAD) ? DAC_READ : DAC_WRITE;

    n = DAC_DATA0;                      /* now read until index changes */
    pvd->dacDACDataCur.dac_bRed = INB(PORT_VGADACDATA);

    if (INB(PORT_VGADACWRITE) == pvd->regDACIndx)
    {
      n++;
      pvd->dacDACDataCur.dac_bGreen = INB(PORT_VGADACDATA);
      if (INB(PORT_VGADACWRITE) == pvd->regDACIndx)
      {
        n++;
      }
    }
    pvd->stateDAC |= DAC_DATA2-n;       /* update state with rgb index    */

    OUTB(PORT_VGADACREAD, 0);           /* prepare to read out entire DAC */
    pbDACData = (PBYTE)pvd->adacDACData;
    for (i=0; i<MAX_DACREGS*3; i++)
      *pbDACData++ = INB(PORT_VGADACDATA);

  }

  /*            start */
#ifdef   SVGA
  if (ulSVGAAdapterType == S3_ADAPTER)             /* save DAC for S3 only */
  {
     if (ulSVGADACFamily != DEFAULT_DAC)           /* valid DAC identified */
     {
        if (ulSVGADACFamily != S3_BT485DAC)        /* 44 pin DAC           */
        {
           if (pvd->vvMode.vvm_nBitCount > 8)      /* more than 256 colors */
           {
              INB(PORT_VGADACREAD);
              for(i=0;i<4;i++) INB(PORT_VGADACMASK);
              pvd->VdmDataX.DACreg[0] = INB(PORT_VGADACMASK);  /*save 1 val*/
              INB(PORT_VGADACREAD);                /* reset DAC            */
              OUTB(PORT_VGADACMASK, 0xff);         /* lock DAC access      */
           }                                       /* end > 256 cols test  */
           else
              pvd->VdmDataX.DACreg[0] = 0;         /* set DAC value = 0    */
        }                                          /* end not BT DAC       */

        else                                       /* Brooktree 485 DAC    */
        {
//         if  ((pvd->vvMode.vvm_nBitCount > 8) || /* more than 256 colors */
//              ((pvd->vvMode.vvm_nBitCount == 8) &&   /* 1280x1024x256    */
//               (pvd->vvMode.vvm_nRows == 1024)))
//         {
              bIndx = INB(PORT_COLRCRTINDX); /* get CRT index *//*          */
              OUTW(PORT_COLRCRTINDX, 0xa039);      /* unlock S3 register   */
              OUTB(PORT_COLRCRTINDX, 0x55);        /* S3's key to the DAC  */

                                                   /* access Command Reg 0 */
              OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x01));
              pvd->VdmDataX.DACreg[0] = INB(PORT_VGADACMASK);  /* save CR0 */

                                                   /* access Command Reg 1 */
              OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x02));
              pvd->VdmDataX.DACreg[1] = INB(PORT_VGADACWRITE); /* save CR1 */

              pvd->VdmDataX.DACreg[2] = INB(PORT_VGADACDATA);  /* save CR2 */

                                                   /* access Command Reg 3 */
              OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x01));
              OUTB(PORT_VGADACMASK, 0x80);
              OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc));
              OUTB(PORT_VGADACWRITE, 0x01);
              OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x02));
              pvd->VdmDataX.DACreg[3] = INB(PORT_VGADACMASK);  /* save CR3 */

                                                   /* disable DAC access   */
              OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc));
              OUTW(PORT_COLRCRTINDX, 0x0039);      /* lock S3 register     */
              OUTB(PORT_COLRCRTINDX,bIndx); /* restore index */ /*          */
//         }                                       /* end >256 | 1280 res  */
        }                                          /* end Brooktree 485    */
     }                                             /* end DAC present test */
  }                                                /* end S3 adapter test  */
#endif
  /*            end   */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvRestoreDACState()
 *
 * DESCRIPTION   = Restore DAC state to hardware
 *
 *                 Restore the DAC's internal state.  Specifically, this is:
 *                     - Read/Write mode
 *                     - 0 (normal), 1 or 2 bytes read/written
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvRestoreDACState(register HVDM hvdm)
{
  BYTE bIndx;                                                   /*          */
  register INT i,n;
  register PVDMDATA pvd = pVDMData(hvdm);

  i = pvd->regDACIndx;
  n = pvd->stateDAC&DAC_DATAMASK;

  if ((pvd->stateDAC&DAC_RWMASK) == DAC_READ)
  {

    /*
    ** Left in READ state, so write to the READ port,
    ** and do the appropriate number of IN instructions
    */

    OUTB(PORT_VGADACREAD,
         i);

    if (n > DAC_DATA0)
      INB(PORT_VGADACDATA);

    if (n > DAC_DATA1)
      INB(PORT_VGADACDATA);
  }

  else
  {

    /*
    ** Left in WRITE state, so write to the WRITE port,
    ** and do the appropriate number of OUT instructions
    */

    OUTB(PORT_VGADACWRITE,
         i);
    i &= MAX_DACREGS-1;                 /* insurance! (never assume the VDM  */
                                        /* always uses index values in-range)*/

    if (n > DAC_DATA0)
      OUTB(PORT_VGADACDATA,
           pvd->dacDACDataCur.dac_bRed);

    if (n > DAC_DATA1)
      OUTB(PORT_VGADACDATA,
           pvd->dacDACDataCur.dac_bGreen);
  }
    /*            start */
#ifdef   SVGA
 if (pvd->flVDMXVideo & VDMX_RESTOREBTDAC)           /*only do once*/
 {
  if (ulSVGAAdapterType == S3_ADAPTER)               /* save DAC for S3 only */
  {
     if (ulSVGADACFamily != DEFAULT_DAC)             /* valid DAC identified */
     {
        if (ulSVGADACFamily != S3_BT485DAC)          /* 44 pin DAC           */
        {
//         if (pvd->vvMode.vvm_nBitCount > 8)        /* more than 256 colors */
//         {
                 INB(PORT_VGADACREAD);
                 for(i=0;i<4;i++) INB(PORT_VGADACMASK);
                 OUTB(PORT_VGADACMASK, pvd->VdmDataX.DACreg[0]); /* set 1 val*/
                 INB(PORT_VGADACREAD);               /* reset DAC            */
                 OUTB(PORT_VGADACMASK, 0xff);        /* lock DAC access      */
//         }                                         /* end > 256 cols test  */
        }                                            /* end not BT DAC       */

        else                                         /* Brooktree 485 DAC    */
        {
//         if  ((pvd->vvMode.vvm_nBitCount > 8) ||   /* more than 256 colors */
//              ((pvd->vvMode.vvm_nBitCount == 8) && /* **or** 1280x1024x256 */
//               (pvd->vvMode.vvm_nRows == 1024)))
//
//         {
              /*
              ** This routine gets called twice but we should only restore
              ** the Brooktree DAC once otherwise weird things happen
              */
//            if (!(pvd->flVDMXVideo & VDMX_RESTOREBTDAC))  /*first time thru*/
//               pvd->flVDMXVideo |= VDMX_RESTOREBTDAC;     /*let it be known*/
//            else
//            {
                 bIndx = INB(PORT_COLRCRTINDX);  /* get index *//*          */
                 OUTW(PORT_COLRCRTINDX, 0xa039);     /* unlock S3 register   */
                 OUTB(PORT_COLRCRTINDX, 0x55);       /* S3's key to the DAC  */

                                                     /* access Command Reg 0 */
                 OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x01));
                 OUTB(PORT_VGADACMASK, pvd->VdmDataX.DACreg[0]);  /* set CR0 */

                                                     /* access Command Reg 1 */
                 OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x02));
                 OUTB(PORT_VGADACWRITE, pvd->VdmDataX.DACreg[1]); /* set CR1 */

                 OUTB(PORT_VGADACDATA, pvd->VdmDataX.DACreg[2]);  /* set CR2 */

                                                     /* access Command Reg 3 */
                 OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x01));
                 OUTB(PORT_VGADACMASK, 0x80);
                 OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc));
                 OUTB(PORT_VGADACWRITE, 0x01);
                 OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc | 0x02));
                 OUTB(PORT_VGADACMASK, pvd->VdmDataX.DACreg[3]);  /* set CR3 */

                                                     /* disable DAC access   */
                 OUTB(PORT_COLRCRTDATA, (INB(PORT_COLRCRTDATA) & 0xfc));
                 OUTW(PORT_COLRCRTINDX, 0x0039);     /* lock S3 register     */
                 OUTB(PORT_COLRCRTINDX,bIndx); /*restore index*//*          */
//               pvd->flVDMXVideo &= ~VDMX_RESTOREBTDAC; /* reset indicator  */
//            }                                      /* end RESTOREBTDAC test*/
//         }                                         /* end >256 | 1280 res  */
        }                                            /* end Brooktree 485    */
     }                                               /* end DAC present test */
  }                                                  /* end S3 adapter test  */
 }                                      /* end RESTOREBTDAC test*/
#endif
  /*            end   */
}

#endif

/***************************************************************************
 *
 * FUNCTION NAME = vvDisableDisplay(hvdm)
 *
 * DESCRIPTION   = Disable display
 *
 *                 This turns the video signal off, helping to hide
 *                 unsightly adapter reprogramming.  A side-effect of this
 *                 service is that the VDM's virtual MISCOUT register (for
 *                 EGA/VGA) is transferred to the physical hardware, so that
 *                 we can make at least a *few* assumptions about the
 *                 hardware state.
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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


  if (pvd->flVDMVideo&VDM_FGND)
  {

#ifdef   MONO
    OUTB(PORT_MONOMODE,
         pvd->regMode&~MONOMODE_ENABLE);
#endif

#ifdef   CGA
    OUTB(PORT_CGAMODE,
         pvd->regMode&~CGAMODE_ENABLE);
#endif

#ifdef   EGAVGA

    /*
    ** If we're the display owner, insure any 8514/A is disabled
    */

    if (pvd->flVDMXVideo&VDMX_DSPOWNER)
        if (flVVD&VVD_8514PRESENT) /*                                     */
           OUTW(A8514_ADVCTRL,
              !ADVCTRL_VGADISABLE|ADVCTRL_OUTPUTPIN|!ADVCTRL_DOTCLOCK);

    INB(PORT_COLRSTATUS1);         /* reset the ATC to index-state first  */
    INB(PORT_MONOSTATUS1);         /* hit the mono port too, just in case */
    OUTB(PORT_ATC0,
         pvd->regATCIndx&~ATCPAL_ENABLE);
#endif
  }
}

/***************************************************************************
 *
 * FUNCTION NAME = vvEnableDisplay()
 *
 * DESCRIPTION   = Enable display
 *
 *                 This turns the video signal on, after all video adapter
 *                 reprogramming is complete.  Also, since vvRestoreIOState
 *                 could not properly update the particular register involved
 *                 (lest it re-enable the screen before we're ready), we take
 *                 care of that last little "bit" of virtual-to-physical
 *                 restoration here.
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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


  if (pvd->flVDMVideo&VDM_FGND)
  {

#ifdef   MONO
    OUTB(PORT_MONOMODE,
/* 73042 pvd->regMode); */
         pvd->regMode | MONOMODE_ENABLE);                            /* 73042 */
#endif

#ifdef   CGA
    OUTB(PORT_CGAMODE,
         pvd->regMode);
#endif

#ifdef   EGAVGA
    register INT i;

    INB(PORT_COLRSTATUS1);        /* reset the ATC to INDEX-state first     */
    INB(PORT_MONOSTATUS1);        /* hit the mono port too, just in case    */
    i = pvd->regATCIndx;                         /* get current index value */
    OUTB(PORT_ATC0,
         i);                      /* store it in the ATC index register     */

    /*
    ** If not in DATA mode, cycle back to INDEX mode
    */

    if (pvd->stateATC != ATC_DATA)
    {
      INB(PORT_COLRSTATUS1);      /* reset the ATC to INDEX-state first     */
      INB(PORT_MONOSTATUS1);      /* hit the mono port too, just in case    */
    }
#endif
  }
}

#ifdef   CGA

/***************************************************************************
 *
 * FUNCTION NAME = VVForceDisplay()
 *
 * DESCRIPTION   = Force display on (for VKBD)
 *
 *                 This forces the video signal on, on request from VKBD (to
 *                 insure that the screen is not left indefinitely disabled
 *                 while in a keyboard-paused state).
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 set virtual enable bit
 *                 turn on the physical enable bit
 *
 ****************************************************************************/

VOID EXPENTRY VVForceDisplay()
{
  VDMData.regMode |= CGAMODE_ENABLE;
  OUTB(PORT_CGAMODE,
       VDMData.regMode);
}

#endif                                           /* CGA                     */

/***************************************************************************
 *
 * FUNCTION NAME = vvDisableVRAM(hvdm)
 *
 * DESCRIPTION   = Disable VRAM
 *
 *                 Disable address decode for the display buffer from
 *                 the system.  This is necessary for situations where
 *                 a Seamless application is running on the XGA desktop
 *                 interfering with the secondary VGA screen because
 *                 the Seamless XGA         driver is using the 64K
 *                 aperture to update the application window.
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/
#ifdef VGA                                                     /*           */
VOID PRIVENTRY vvDisableVRAM(register HVDM hvdm)               /*           */
{                                                              /*           */
  register PVDMDATA pvd = pVDMData(hvdm);                      /*           */
                                                               /*           */
  OUTB(PORT_MISCOUT,(pvd->regMiscOut & ~MISCOUT_ENABLERAM));   /*           */
                                                               /*           */
}                                                              /*           */
#endif                                                         /*           */
#pragma  END_SWAP_CODE

