/*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 = VVINIT.C
 *
 * DESCRIPTIVE NAME = Virtual Video Device Driver Initialization
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION  This module contains the VVD's initialization code.
 *
 * FUNCTIONS    VDDInit()           VVD initialization
 *              vvEditVideoTables() Edit global tables for adapter if necessary
 *              vvFindMono()        Test if a Monochrome adapter is installed
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


#include <mvdm.h>
#include <vvd.h>
#include "vvdp.h"
#include <propname.h>
#ifdef  GALE                                                            //J-TS00V
#include "vvgale.h"                                                     //J-TS00V
#endif  //GALE                                                          //J-TS00V

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif
extern ULONG npgActive[];             /* moved from VVSTATE.C              */
extern ULONG flVVD;
extern PBOOL pflVDMBusy;              /* offset to WakeIdle flag           */
#pragma  BEGIN_SWAP_DATA
extern ULONG ulAdapter;
extern PSZ pszVVDName;
extern PBYTE pPhysVRAM;
extern PVDM pvdmPhysVRAM;
extern ULONG npgPhysVRAM;
extern ULONG npgPlane;
extern PLE apleAll[];
extern HMXSEM hmxWindowedEvent;
extern HEVSEM hevWindowedEvent;
extern HHOOK hhookEventTimer;

#ifdef   EGAVGA
extern HMXSEM hmxPhysLatch;
extern HMXSEM hmxPhysPageEvent;
#endif

#ifdef   VGA
extern BYTE aregSEQInit[MAX_SEQREGS];
extern BYTE aregGDCInit[MAX_GDCREGS];            /*                         */
extern BYTE aregCRTInit[MAX_CRTREGS];            /*                         */
BOOL   flDualDisplayConf = FALSE;                /*                         */
#endif

#ifdef   SVGA
extern BYTE aregATIInit[ATI_TOTAL_INITREGS];
extern BOOL     flBgndExecSupported;                            /*            */
extern ULONG ulSVGADACFamily;                    /*                          */
#endif

#ifdef   PROPERTIES
extern SZ szPropInt10Emulate;
extern SZ szPropRtrcEmulate;
extern SZ szPropModeRestrict;
extern SZ szPropNoRestrict;
extern SZ szPropCGARestrict;
extern SZ szPropIOTrap;                                         /*            */

   #ifndef  CGA
extern SZ szPropMONORestrict;
   #endif
extern SZ szPropUpdateWindow;

/* extern  SZ      szPropSyncOutput;                                        */

extern SZ szPropInt2F;
extern SZ szPropOnDemandAlloc;
#endif

#ifdef   VDDSTRICT
extern ULONG nbVDMData;
#endif
#pragma  END_SWAP_DATA

#ifdef   EGAVGA
   #pragma  BEGIN_GLOBAL_DATA
extern HEVSEM hevControllerEvent;
   #pragma  END_GLOBAL_DATA
#endif
#pragma  BEGIN_INIT_CODE

/***************************************************************************
 *
 * FUNCTION NAME = VDDInit()
 *
 * DESCRIPTION   = VVD initialization
 *
 *                 This routine is defined as the device driver entry point,
 *                 and is called during system initialization.
 *
 * INPUT         = None
 *
 * OUTPUT        = SUCCESS
 *                     TRUE
 *                 FAILURE
 *                     FALSE (ie, hardware missing, or reserved page conflict)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * PSEUDO-CODE
 *                 verify existence of physical hardware
 *                 determine primariness/secondariness
 *                 locate and reserve physical VRAM pages
 *                 obtain global linear mapping to physical VRAM
 *                 define DosRequestVDD/VDHRequestVDD procedure
 *                 define screen-enable-during-pause procedure
 *
 ****************************************************************************/

BOOL EXPENTRY VDDInit(register PSZ pszInit)
{
#ifdef VGA
  PSZ   pInit = pszInit;                                /*           */
#endif
  register INT i;
  PVOID pLowMemAlias;
  register ULONG nKB;
  BOOL fSuccess = TRUE;
  VPBOUND vpbUpdateGrfx =
  {
    1,600,1
  }
  ;
  AssertTRUE(nbVDMData == sizeof(PERVDMDATA));

#ifdef   DCR1013

  while (pszInit = STRTOKEN(pszInit))

    if (STRCOMPARE(pszInit,
                   "/wingraph",
                   FALSE) == 0)
      flVVD |= VVD_GRFXALLOWED;
#endif

#ifdef VGA                                                      /*            */
  while (pInit = STRTOKEN(pInit))

    if (STRCOMPARE(pInit,
                   "/dual",
                   FALSE) == 0)
      flDualDisplayConf = TRUE;
#ifdef SVGA
    else if (STRCOMPARE(pInit,                                  /*            */
                   "/bgexec",
                   FALSE) == 0)
      flBgndExecSupported = TRUE;
#endif
#endif
  /*
  ** NOTES ON SEMAPHORE HIERARCHY
  ** (maintained in vvinit.c and vvuser.c)
  **
  ** The Video VDD's semaphore hierarchy is as follows:
  **
  **  1. hmxWindowedState
  **  2. hmxVideoState
  **  3. hvdmController
  **  4. hmxPhysPageEvent
  **  5. hmxWindowedEvent
  **  6. hmxPhysLatch
  **
  ** The per-VDM semaphores are first, because we generally enter the VDD
  ** in (or on behalf of) a VDM's context.  hvdmController is next because
  ** of the constraints of our interface with the PM display driver (see
  ** vvGetPhysBytes and vvFreePhysBytes for more details).  From that point
  ** on, the semaphores are basically in order of high-level to low-level
  ** operation.
  **
  ** Note that driver entry points can enter the hierarchy at any point,
  ** but must take care to not call routines that require semaphores at some
  ** higher point.  I need to eventually build some assertion checking into
  ** the RequestMutexSem macro, but because some are per-vdm and some are
  ** not conventional (ie, hvdmController), it'll take some time....
  */

  /*
  ** Allocate all global semaphores
  */

#ifdef   EGAVGA

  if (!CreateEventSem(&hevControllerEvent))
    fSuccess = FALSE;

  if (!CreateMutexSem(&hmxPhysPageEvent))
    fSuccess = FALSE;

  if (!CreateMutexSem(&hmxPhysLatch))
    fSuccess = FALSE;
#endif

  if (!CreateEventSem(&hevWindowedEvent))
    fSuccess = FALSE;

  if (!CreateMutexSem(&hmxWindowedEvent))
    fSuccess = FALSE;

  /*
  ** Allocate global context timer hook
  */

  if (!(hhookEventTimer = VDHAllocHook(VDH_TIMER_HOOK,
                                       (PFNARM)VVEventTimer,
                                       0)))
    fSuccess = FALSE;

  /*
  ** Get access to low memory
  */

  pLowMemAlias = VDHAllocPages(LOWMEM_START,
                               LOWMEM_PAGES,
                               VDHAP_SYSTEM|VDHAP_PHYSICAL);

  if (!pLowMemAlias)
    fSuccess = FALSE;

#ifdef  GALE                                                            //J-TS00V
  {                                                                     //J-TS00V
    extern UCHAR  FlagXGA;                                              //J-TS00V
    extern USHORT GaleScroll;                                           //J-TS00V
    extern USHORT APAWidthText;                                         //J-TS00V
    PSZ p = pszInit;                                                    //J-TS00V
                                                                        //J-TS00V
        // OEMHELP in OS2LDR checks VGA wrap function                   //J-TS00V
        // and reports the result trough int 60h vector.                //J-TS00V
                                                                        //J-TS00V
    if (*(UCHAR *)&(pVDMBase(pLowMemAlias)->rb_avpIVT[0x60])) {         //J-TS00V
      GaleScroll   = GALE_HS_ON;                                        //J-TS00V
      APAWidthText = DOT_WIDTH_COMPACT / 8;                             //J-TS00V
    } else {                                                            //J-TS00V
      GaleScroll   = GALE_HS_LC;                                        //J-TS00V
      APAWidthText = DOT_WIDTH_WIDE / 8;                                //J-TS00V
    }                                                                   //J-TS00V
    *(UCHAR *)&(pVDMBase(pLowMemAlias)->rb_avpIVT[0x60]) = 0;           //J-TS00V
                                                                        //J-TS00V
    while (p = STRTOKEN(p)) {                                           //J-TS00V
      if (STRCOMPARE(pszInit, "/HS=OFF", FALSE) == 0) {                 //J-TS00V
        GaleScroll   = GALE_HS_OFF;                                     //J-TS00V
        APAWidthText = DOT_WIDTH_COMPACT / 8;                           //J-TS00V
                                                                        //J-TS00V
      } else if (STRCOMPARE(pszInit, "/HS=ON", FALSE) == 0) {           //J-TS00V
        GaleScroll   = GALE_HS_ON;                                      //J-TS00V
        APAWidthText = DOT_WIDTH_COMPACT / 8;                           //J-TS00V
                                                                        //J-TS00V
      } else if (STRCOMPARE(pszInit, "/HS=LC", FALSE) == 0) {           //J-TS00V
        GaleScroll   = GALE_HS_LC;                                      //J-TS00V
        APAWidthText = DOT_WIDTH_WIDE / 8;                              //J-TS00V
      }                                                                 //J-TS00V
    }                                                                   //J-TS00V
                                                                        //J-TS00V
    VVCheckXGAAdapter();                                                //J-TS00V
    if (FlagXGA && (GaleScroll != GALE_HS_OFF))                         //J-TS00V
      APAWidthText = DOT_WIDTH_WIDE / 8;                                //J-TS00V
  }                                                                     //J-TS00V
#endif  //GALE                                                          //J-TS00V

  /*
  ** Begin equipment checks
  */

  vvFindMono(pLowMemAlias);

#ifdef   MONO

  if (!(flVVD&VVD_MONOPRESENT))
    fSuccess = FALSE;                            /* No MPA-Mono installed   */
#endif

#ifdef   EGAVGA

  if (!pVDMBase(pLowMemAlias)->rb_nVRows)
    fSuccess = FALSE;                            /* No EGA/VGA installed    */
#endif


  /*
  ** If we made it past the equipment checks
  */

  if (fSuccess)
  {

    /*
    ** Note that VVD_PRIMARY *would* be set whenever the equipment flags
    ** so indicate, but under OS/2, a mono monitor can never be primary
    */

#ifndef  MONO
    flVVD |= VVD_PRIMARY;
#endif

    /*
    ** Mark VRAM pages as reserved
    */

#ifdef   EGAVGA

    if (flVVD&VVD_MONOPRESENT)
    {
      fSuccess = VDHReservePages(pvdmPhysVRAM,
                                 PAGESFROMBYTES(MONOMEM_START-EGAVGAMEM_START)
         ) && VDHReservePages((PBVDM)(MONOMEM_START+MONOMEM_LEN),
                              npgPhysVRAM-PAGESFROMBYTES(MONOMEM_START+
                              MONOMEM_LEN-EGAVGAMEM_START));
    }

    else
#endif
         fSuccess = VDHReservePages(pvdmPhysVRAM,
                                    npgPhysVRAM);
  }

  /*
  ** If VRAM pages were successfully reserved
  */

  if (fSuccess)
  {

    /*
    ** Obtain global addressability to physical VRAM
    */

    pPhysVRAM = VDHAllocPages((PBVDM)VRAM_START,
                              PAGESFROMBYTES(VRAM_LEN),
                              VDHAP_SYSTEM|VDHAP_PHYSICAL);

    if (pPhysVRAM)
    {

      /*
      ** Install user event hooks
      */

      VDHInstallUserHook(VDM_CREATE,
                         (PUSERHOOK)VVCreate);
      VDHInstallUserHook(VDM_CREATE_DONE,
                         (PUSERHOOK)VVCreateDone);/*                        */
      VDHInstallUserHook(VDM_FOREGROUND,
                         (PUSERHOOK)VVSetFgnd);
      VDHInstallUserHook(VDM_BACKGROUND,
                         (PUSERHOOK)VVSetBgnd);
      VDHInstallUserHook(VDM_CODEPAGE_CHANGE,
                         (PUSERHOOK)VVChangeCodePage);
      VDHInstallUserHook(VDM_TITLE_CHANGE,
                         (PUSERHOOK)VVChangeTitle);
      VDHInstallUserHook(VDM_TERMINATE,
                         (PUSERHOOK)VVDestroy);

#ifdef   EGAVGA

      /*
      ** Determine the size of physical memory planes
      */

      nKB = (pVDMBase(pLowMemAlias)->rb_bVInfo&BIOSVINFO_MEMMASK);
      nKB = ((nKB >> ZEROBITS(BIOSVINFO_MEMMASK))+1)*(16*1024);

      /*
      ** Save # pages per plane
      */

      npgPlane = nKB/PAGESIZE;

      /*
      ** Make any necessary adapter-specific table edits
      */

      vvEditVideoTables(pLowMemAlias);

      /*
      ** Initialize the physical page usage table
      */

      vvUpdatePhysPageMap(NULL);
#endif

      /*
      ** Set VDD name to secondary name if secondary display
      */

      pszVVDName = VVD_NAME1;

      if (!(flVVD&VVD_PRIMARY))
        pszVVDName = VVD_NAME2;
      VDHRegisterVDD(pszVVDName,
                     VVSysReqProc,
                     VVDevReqProc);

#ifdef   CGA
      VDHRegisterScreenProc(VVForceDisplay);
#endif

#ifdef   PROPERTIES

      if (!VDHRegisterProperty(szPropInt10Emulate, /* property name         */
                               NULL,             /* no help file            */
                               0,                /* no help id              */
                               VDMP_BOOL,        /* type                    */
                               VDMP_ORD_OTHER,   /* no ordinal              */
                               0,                /* modifiable after
                                                    creation                */
                               (VOID *)TRUE,     /* default                 */
                               NULL,             /* validation info         */
                               VVSetInt10Emulation/* function               */
                                  ))
        fSuccess = FALSE;

      if (!VDHRegisterProperty(szPropRtrcEmulate, /* property name          */
                               NULL,             /* no help file            */
                               0,                /* no help id              */
                               VDMP_BOOL,        /* type                    */
                               VDMP_ORD_OTHER,   /* no ordinal              */
                               0,                /* modifiable after
                                                    creation                */

/*                  (VOID*)FALSE,                  default                  */

                               (VOID *)TRUE,     /* default ** Temp Change  */
                               NULL,             /* validation info         */
                               VVSetRetraceEmulation/* function             */
                                  ))
        fSuccess = FALSE;

   #ifdef   EGA

      /*
      ** For the EGA, we have to eliminate one of the restriction
      ** strings;  we either move the mono string on top of the color
      ** string, or nullify the mono string.
      **
      ** We don't have to make any adjustments for the other drivers:
      ** the mono driver doesn't have PROPERTIES support, the CGA driver
      ** just contains the color string, and the VGA driver always
      ** contains both, because VGA can support both color and mono
      ** configurations.
      **
      ** FLAG: 20-Aug-90:    The last bit about VGA is true
      ** with color monitors, but what about mono monitors?
      */

      if (pVDMBase(pLowMemAlias)->rb_bVMode == BIOSVMODE_MONO80)
        memcpy(szPropCGARestrict,
               szPropMONORestrict,
               sizeof(PROP_NAME_MONORESTRICT));
      szPropMONORestrict[0] = 0;
   #endif

      if (!VDHRegisterProperty(szPropModeRestrict, /* property name         */
                               NULL,             /* no help file            */
                               0,                /* no help id              */
                               VDMP_ENUM,        /* type                    */
                               VDMP_ORD_OTHER,   /* no ordinal              */
                               VDMP_CREATE,      /* NOT modifiable after
                                                    creation                */
                               szPropNoRestrict, /* default                 */
                               szPropNoRestrict, /* validation info         */
                               NULL              /* no function             */
                                  ))
        fSuccess = FALSE;

      if (!VDHRegisterProperty(szPropUpdateWindow, /* property name         */
                               NULL,             /* no help file            */
                               0,                /* no help id              */
                               VDMP_INT,         /* type                    */
                               VDMP_ORD_OTHER,   /* no ordinal              */
                               0,                /* modifiable after
                                                    creation                */
                               (VOID *)(TICKS_DIRTY *TIMER_CHECK/100), /*
                                                    default                 */
                               SSToDS(&vpbUpdateGrfx), /* validation info   */
                               VVSetUpdateFrequency/* function              */
                                  ))
        fSuccess = FALSE;

/*   if (!VDHRegisterProperty(                                              */
/*           szPropSyncOutput,    property name                             */
/*           NULL,                no help file                              */
/*           0,                   no help id                                */
/*           VDMP_BOOL,           type                                      */
/*           VDMP_ORD_OTHER,      no ordinal                                */
/*           0,                   modifiable after creation                 */
/*           (VOID*)TRUE,         default                                   */
/*           NULL,                validation info                           */
/*           VVSetSyncOutput      function                                  */
/*        )                                                                 */
/*      )                                                                   */
/*       fSuccess = FALSE;                                                  */

      if (!VDHRegisterProperty(szPropInt2F,      /* property name           */
                               NULL,             /* no help file            */
                               0,                /* no help id              */
                               VDMP_BOOL,        /* type                    */
                               VDMP_ORD_OTHER,   /* no ordinal              */
                               0,                /* modifiable after
                                                    creation                */
                               (VOID *)FALSE,    /* default                 */
                               NULL,             /* validation info         */
                               VVSetInt2F        /* function                */
                                  ))
        fSuccess = FALSE;

      if (!VDHRegisterProperty(szPropOnDemandAlloc, /* property name        */
                               NULL,             /* no help file            */
                               0,                /* no help id              */
                               VDMP_BOOL,        /* type                    */
                               VDMP_ORD_OTHER,   /* no ordinal              */
                               0,                /* modifiable after
                                                    creation                */
                               (VOID *)TRUE,     /* default                 */
                               NULL,             /* validation info         */
                               VVSetOnDemandAlloc/* function                */
                                  ))
        fSuccess = FALSE;
                                                  /*            */
        VDHRegisterProperty(szPropIOTrap,         /* property name           */
                            NULL,                 /* no help file            */
                            0,                    /* no help id              */
                            VDMP_BOOL,            /* type                    */
                            VDMP_ORD_OTHER,       /* no ordinal              */
                            VDMP_CREATE,          /* not modifiable after    */
                                                  /* creation                */
                            (VOID *)TRUE,         /* default                 */
                            NULL,                 /* validation info         */
                            NULL                  /* no function             */
                            );
#endif                                           /* PROPERTIES              */
    }

    else
    {
      fSuccess = FALSE;

#ifdef   EGAVGA

      if (flVVD&VVD_MONOPRESENT)
      {
        VDHUnreservePages(pvdmPhysVRAM,
                          PAGESFROMBYTES(MONOMEM_START-EGAVGAMEM_START));
        VDHUnreservePages((PBVDM)(MONOMEM_START+MONOMEM_LEN),
                          npgPhysVRAM-PAGESFROMBYTES(MONOMEM_START+MONOMEM_LEN
                             -EGAVGAMEM_START));
      }

      else
#endif
           VDHUnreservePages(pvdmPhysVRAM,
                             npgPhysVRAM);
    }
  }
  VDHFreePages(pLowMemAlias);

  /*
  ** If installation failed, free all context hooks/semaphores
  */

  if (!fSuccess)
  {
    VDHFreeHook(hhookEventTimer);
    DestroyEventSem(hevWindowedEvent);
    DestroyMutexSem(hmxWindowedEvent);

#ifdef   EGAVGA
    DestroyMutexSem(hmxPhysPageEvent);
    DestroyEventSem(hevControllerEvent);
#endif
  }

#ifdef   SVGA
  ulSVGADACFamily = vvGetDACType();              /*            */
#endif

  /*
  ** Get the offset the WakeIdle Flag                                       
  */

  if (!pflVDMBusy)                               /*                         */
    pflVDMBusy = VDHGetBusyFlagPtr();            /*                         */
  return  fSuccess;
}
/*            start */
#ifdef   SVGA
/*****************************************************************************
 *
 * FUNCTION NAME = ResetDAC()                                            
 *
 * DESCRIPTION   = Resets the DAC
 *
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = NONE
 * RETURN-ERROR  = NONE
 *
 ****************************************************************************/
void ResetDAC(void)
{
    USHORT i;

    /*
    ** Reset command register state
    */
    inp(PORT_VGADACREAD);
    outp(PORT_VGADACMASK,0xff);
//  for(i=0;i<4;i++) inp(PORT_VGADACMASK);
}
/*****************************************************************************
 *
 * FUNCTION NAME = IsBrooktreeDAC()                                          
 *
 * DESCRIPTION   = If Brooktree DAC identified, return TRUE.
 *                 This is specific for the BT485 RAMDAC used by S3
 *                 because in order to get to the DAC, specific
 *                 S3 registers must be manipulated.
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = 1
 * RETURN-ERROR  = 0
 *
 ****************************************************************************/
int IsBrooktreeDAC(void)
{
    BYTE bIndx;                                                 /*          */
    UCHAR x;
    USHORT i;

    bIndx = INB(PORT_COLRCRTINDX);      /* get current index */ /*          */
    outpw(PORT_COLRCRTINDX, 0xa039);    /* unlock S3 register         */

    outp(PORT_COLRCRTINDX, 0x55);       /* setup for DAC Control      */
    i = inp(PORT_COLRCRTDATA);
    i &= 0xFC;
    i |= 0x02;
    outp(PORT_COLRCRTDATA, i);          /* set RS[1:0] = 1,0          */

    /*
    ** Read the ID
    */
    x = (UCHAR) inp(PORT_VGADACMASK);   /* get ID from Status Reg     */
    i &= 0xFC;
    outp(PORT_COLRCRTDATA, i);          /* set RS[1:0] = 0,0 (reset)  */
    OUTB(PORT_COLRCRTINDX,bIndx);       /* restore the index */ /*          */

    ResetDAC();

    if (x != 0xff)
      return(1);                        /* it's a BT 485 RAMDAC!!     */
    else
      return(0);

}
/*****************************************************************************
 *
 * FUNCTION NAME = vvGetDACType()                                        
 *
 * DESCRIPTION   = Identifies DAC and returns one of the following:
 *                    1  44 pin DAC
 *                    3  Brooktree 485
 *
 *
 * INPUT         = NONE
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL = 0-4 Supported DAC
 * RETURN-ERROR  = -1  Unsupported DAC
 *
 ****************************************************************************/
int vvGetDACType(void)
{
  USHORT i;
  UCHAR x;

  /*
  ** Reset command register state
  */
//_asm{int 3};      //yee dbug
  inp(PORT_VGADACREAD);
  outp(PORT_VGADACMASK,0xff);       /* set mask register = ff   */

  if (IsBrooktreeDAC())
    return(3);                      /* it's Brooktree 485       */

  return(1);

}
#endif
/*            end */
#ifdef   EGAVGA

/***************************************************************************
 *
 * FUNCTION NAME = vvEditVideoTables()
 *
 * DESCRIPTION   = Edit global tables for adapter if necessary
 *
 *                 This routine performs adapter-specific VDD table editing,
 *                 if necessary.
 *
 * INPUT         = pLowMemAlias -> low memory
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvEditVideoTables(PVOID pLowMemAlias)
{

   #ifdef   VGA
  register INT i;
           USHORT Addr_6845;                                  /*            */
           UCHAR  SaveIndex;                                  /*            */
   #endif

   #ifdef   TSENG
  PORT port;
  register PPLE pple;
   #endif
  PBVDM pvdmROM;
  register PROMHDR pROMAlias;

  /*
  ** Pick likely starting point for Video ROM
  */

  pvdmROM = PFROMVADDR(SEGMENTOF16(pVDMBase(pLowMemAlias)->rb_avpIVT
     [BIOSINT_VIDEOGRAPH]),
                       0);
  pROMAlias = VDHAllocPages(pvdmROM,
                            PAGESFROMBYTES(0x10000),
                            VDHAP_SYSTEM|VDHAP_PHYSICAL);
  AssertNONZERO(pROMAlias);

  if (pROMAlias)
  {

   #ifdef   TSENG

    if (DWORDOF(pROMAlias->romhdr_abFiller[0x73],
                0) == 0x6e657354)
    {
      ulAdapter = ADAPTER_TSENG;
      pple = apleAll;

      while (pple->ple_port)
      {
        port = pple->ple_port&PORT_MASK;

        if (port == PORT_ATC0)
          pple->ple_nRegs = TOTAL_TSENG_ATCREGS;

        else

          if (port == PORT_SEQINDX)

            pple->ple_nRegs = TOTAL_TSENG_SEQREGS;

          else

            if (port == PORT_GDCINDX)

              pple->ple_nRegs = TOTAL_TSENG_GDCREGS;

            else

              if (port == PORT_COLRCRTINDX)

                pple->ple_nRegs = TOTAL_TSENG_CRTREGS;

        /*
        ** Advance to next port-list entry
        */

        ++pple;
      }

      #ifdef   VDDDEBUG
      PRINTDEBUG("Patched for TSENG adapter\n");
      #endif
    }
   #endif
    VDHFreePages(pROMAlias);
  }

   #ifdef   VGA

  SaveIndex = INB(PORT_SEQINDX);                                /*          */
  for (i = 0; i < MAX_SEQREGS; i++)
  {
    OUTB(PORT_SEQINDX,
         i);
    aregSEQInit[i] = INB(PORT_SEQDATA);
  }
  OUTB(PORT_SEQINDX, SaveIndex);                                /*          */

  SaveIndex = INB(PORT_GDCINDX);                                /*          */
  for (i = 0; i < MAX_GDCREGS; i++)
  {                                              /*                         */
    OUTB(PORT_GDCINDX,
         i);                                     /*                         */
    aregGDCInit[i] = INB(PORT_GDCDATA);          /*                         */
  }                                              /*                         */
  OUTB(PORT_GDCINDX, SaveIndex);                                /*          */

  Addr_6845 = PORT_MONOCRTINDX + ((INB(PORT_GDCPOS1)&01) << 5); /*          */

  SaveIndex = INB(Addr_6845);                                   /*          */
  for (i = 0; i < MAX_CRTREGS; i++)
  {                                              /*                         */
    OUTB(Addr_6845,
         i);                                     /*                         */
    aregCRTInit[i] = INB(Addr_6845+1);           /*                         */
  }                                              /*                         */
  OUTB(Addr_6845, SaveIndex);                                   /*          */

   #endif

   #ifdef   SVGA

  for (i = ATI_START_EXTREGS; i < ATI_END_EXTREGS; i++)
  {
    OUTB(PORT_ATIVGA_INDX,
         i);
    aregATIInit[i-ATI_START_EXTREGS] = INB(PORT_ATIVGA_DATA);
  }
   #endif
}

#endif                                           /* EGAVGA                  */

/***************************************************************************
 *
 * FUNCTION NAME = vvFindMono()
 *
 * DESCRIPTION   = Test if a Monochrome adapter is installed
 *
 *                 This routine checks if a Monochrome adapter/monitor is
 *                 installed It looks for the MONO's 6845 CRTC at I/O ports
 *                 0x3B4 and 0x3B5.  It attempts to read/write to these
 *                 ports and compares the values.
 *
 * INPUT         = None
 *
 * OUTPUT        = TRUE if MONO hardware exists, FALSE if not
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvFindMono(PVOID pLowMemAlias)
{
  BYTE invalue;


  if (pVDMBase(pLowMemAlias)->rb_bVInfo&BIOSVINFO_EGAMONO || pVDMBase
     (pLowMemAlias)->rb_bVFlags&BIOSVFLAGS_VGAMONO)
  {
    npgActive[2] = 8;           /* ((16*1024)/PAGESIZE)*2                   */
    return ;                    /* Mono monitor attached to a VGA/EGA       */
  }

  /*
  ** Select the cursor index register and read its value
  */

  OUTB(PORT_MONOCRTINDX,
       REG_CRTCURLOCLO);
  invalue = INB(PORT_MONOCRTDATA);

  /*
  ** Modify its value
  */

  invalue ^= 0xFF;
  OUTB(PORT_MONOCRTDATA,
       invalue);

  /*
  ** Read the value again;  if changed, assume that MONO is present
  */

  if (invalue == INB(PORT_MONOCRTDATA))
    flVVD |= VVD_MONOPRESENT;

#ifndef MONO                                           /*            */

  else                                                 /*            */

    /*
    ** Fixup for maximum number of monochrome pages                 
    */

    npgActive[2] = 8;    // ((16*1024)/PAGESIZE)*2     /*            */

#endif                                                 /*            */

  /*
  ** Restore its value
  */

  invalue ^= 0xFF;
  OUTB(PORT_MONOCRTDATA,
       invalue);
}

#pragma  END_INIT_CODE

