/*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 = VVCGA.C
 *
 * DESCRIPTIVE NAME = Virtual Video CGA Specific routines
 *
 *
 * VERSION = V2.0
 *
 * DATE      11/10/88
 *
 * DESCRIPTION
 *              This module contains the VVD's VGA specific routines and data.
 *
 *
 * FUNCTIONS
 *
 * NOTES
 *
 *
 * STRUCTURES
 *
 * EXTERNAL REFERENCES
 *
 * EXTERNAL FUNCTIONS
 *
*/


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

#ifdef   VDDSTRICT
MODNAME = __FILE__;
#endif

#pragma  BEGIN_SWAP_DATA

IOH aiohCRTIndx [2] =                   /* 03b4/03d4 */
{
  {
#ifndef VGA
    &VVReadCRTIndxFgnd,
    &VVWriteCRTIndxFgnd,
    &VVReadCRTIndxFgndW,
    &VVWriteCRTIndxFgndW,
#else /* !VGA */
    NULL,
#endif /* !VGA */
  },
  {
    &VVReadCRTIndxBgnd,
    &VVWriteCRTIndxBgnd,
  },
};

IOH aiohCRTData [2] =                   /* 03b5/03d5 */
{
  {
#ifndef VGA
    &VVReadCRTDataFgnd,
    &VVWriteCRTDataFgnd,
#else /* !VGA */
    NULL,
#endif /* !VGA */
  },
  {
    &VVReadCRTDataBgnd,
    &VVWriteCRTDataBgnd,
  },
};

/*  FLAG: nonexistent on EGA,       */
/*  but some ROMs fiddle with it for CGA/MONO compatibility! */

IOH aiohCRTMode [2] =                   /* 03b8/03d8 */
{
  {
#ifdef MONOCGA
    &VVReadModeFgnd,
    &VVWriteModeFgnd,
#else /* MONOCGA */
    NULL,
#endif /* MONOCGA */
  },
  {
    &VVReadModeBgnd,
    &VVWriteModeBgnd,
  },
};

IOH aiohFeatureWrite [2] =              /* 03ba/03da */
{
  {
#ifdef EGAVGA
    &VVReadStatus1Fgnd,
#else /* EGAVGA */
    NULL,
#endif /* EGAVGA */
#ifdef EGA
    &VVWriteFeatureFgnd,
#else /* EGA */
    NULL,
#endif /* EGA */
  },
  {
    &VVReadStatus1Bgnd,
#ifdef VGA
    &VVWriteFeatureBgnd,
#else /* VGA */
    &VVWriteUnknownBgnd,
#endif /* VGA */
  },
};

#ifndef CGA                                                     /*          */

IOH aiohHercCompatibility [2] =         /* 03bf */              /*          */
{                                                               /*          */
  {                                                             /*          */
    NULL,                                                       /*          */
    &VVWriteHercCompatibilityFgnd,                              /*          */
  },                                                            /*          */
  {                                                             /*          */
    NULL,                                                       /*          */
    &VVWriteHercCompatibilityBgnd,                              /*          */
  },                                                            /*          */
};                                                              /*          */

#endif /* !CGA */                                               /*          */

#ifndef MONO

IOH aiohCGALPenReset [2] =              /* 03d9 */
{
  {
    NULL,
  },
  {
    &VVReadUnknownBgnd,
    &VVWriteUnknownBgnd,
  },
};

IOH aiohCGAColor [2] =                  /* 03d9 */
{
  {
    &VVReadCGAColorFgnd,
    &VVWriteCGAColorFgnd,
  },
  {
    &VVReadCGAColorBgnd,
    &VVWriteCGAColorBgnd,
  },
};

IOH aiohCGAUnknown [2] =                /* 03db CGALPenSet   */
{                                       /* 03dc CGALPenReset */
  {
    NULL,
  },
  {
    &VVReadUnknownBgnd,
    &VVWriteUnknownBgnd,
  },
};

#endif /* !MONO */

#ifdef SVGA
 /*
 **
 **  These bit masks determine which indexed registers in each group
 **  are saved/restored. They are initialised to standard VGA registers
 **  and modified during the PMI file parsing to reflect the particular
 **  adapter's extended registers. Note, each array must end with a zero
 **  which will fill the un-initialised elements.
 */

//@V3.0YEE01 BYTE    abCRTMask[32] = {0xff, 0xff, 0xff, 0x01, 0};/* 25 registers           */
BYTE abCRTMask [MAX_CRTREGS] =
{                                       /* 25 VGA registers */
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x00 */
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x10 */
  0xff, 0x00
};
#endif /* SVGA */

PLE pleCRTIndx =                                                /*          */
{
  {
#ifdef MONO
    PORT_MONOCRTINDX,                   /* 03b4 (R/W) */
#else  /* MONO */
    PORT_COLRCRTINDX,                   /* 03d4 (R/W) */
#endif /* MONO */
    &VDMData.regCRTIndx,                                        /*          */
    &VDMData.regCRTIndx,                                        /*          */
    PORTF_COLRMONO                      /* becomes 3b4h when */
                                        /*  bit 0 of MISCOUT is 0 */
      | PORTF_CRTCTRL                   /* can be write protected */
      | WRITE_MANY | READ_MANY | R_EQ_W,                        /*          */
    aiohCRTIndx,                                                /*          */
  },                                                            /*          */
  0,                                                            /*          */
  NULL,                                                         /*          */
#ifdef SVGA                                                     /*          */
  NULL,                                                         /*          */
  NULL,                                                         /*            */
#endif /* SVGA */                                               /*          */
};

PLE pleCRTData =                                                /*          */
{                                                               /*          */
  {                                                             /*          */
#ifdef MONO
    PORT_MONOCRTDATA,                   /* 03b5 (R/W) */        /*          */
#else  /* MONO */
    PORT_COLRCRTDATA,                   /* 03d5 (R/W) */        /*          */
#endif /* MONO */
    &VDMData.aregCRTData[0],                                    /*          */
    &VDMData.aregCRTData[0],                                    /*          */
    PORTF_COLRMONO                      /* becomes 3b5h when */
                                        /*  bit 0 of MISCOUT is 0 */
      | PORTF_CRTCTRL                   /* can be write protected */
      | WRITE_INDX | READ_INDX | R_EQ_W,                        /*          */
    aiohCRTData,                                                /*          */
  },                                                            /*          */
#ifdef MONOCGA
  TOTAL_CGA_CRTREGS,                                            /*          */
#else /* MONOCGA */
  /* SVGA grows this during PMI TRAPREGS processing */          /*          */
  /* VGA changes this to TOTAL_TSENG == MAX if needed */        /*          */
  TOTAL_IBM_CRTREGS,                    /* 19h registers */     /*          */
#endif /* MONOCGA */
  &pleCRTIndx,                                                  /*          */
#ifdef SVGA                                                     /*          */
  &abCRTMask[0],                                                /*          */
  &abCRTMask[0],                                                /*          */
#endif /* SVGA */                                               /*          */
};                                                              /*          */

PLE pleCRTMode =                                                /*          */
{
  {                                                             /*          */
#ifdef MONO
    PORT_MONOMODE,                      /* 03b8 (R/W) */
#else  /* MONO */
    PORT_CGAMODE,                       /* 03d8 (R/W) */
#endif /* MONO */
    &VDMData.regMode,
    &VDMData.regMode,
    PORTF_COLRMONO                      /* becomes 03b8h when */
                                        /*  bit 0 of MISCOUT is 0 */
      | WRITE_MANY | READ_MANY | R_EQ_W,                        /*          */
    aiohCRTMode,                                                /*          */
  },                                                            /*          */
  0,
  NULL,
#ifdef SVGA                                                     /*          */
  NULL,                                                         /*          */
#endif /* SVGA */                                               /*          */
};

PLE pleFeatureWrite =                                           /*          */
{
  {                                                             /*          */
#ifdef MONO
    PORT_MONOSTATUS1,                   /* 03bah (R/O) */
#else  /* MONO */
    PORT_COLRSTATUS1, /*=COLRFEATURE*/  /* 03dah (R/O) */
#endif /* MONO */
    &VDMData.regFeature,                /* R_NE_W! */
    &VDMData.regStatus1,
    PORTF_COLRMONO                      /* becomes 03bah when */
                                        /*  bit 0 of MISCOUT is 0 */
      | WRITE_MANY | READ_MANY | R_NE_W,                        /*          */
    aiohFeatureWrite,                                           /*          */
  },                                                            /*          */
  0,
  NULL,
#ifdef SVGA                                                     /*          */
  NULL,                                                         /*          */
#endif /* SVGA */                                               /*          */
};

#ifndef CGA

PLE pleHercCompatibility =              /* 03bf (W/O) */        /*          */
{                                                               /*          */
  {                                                             /*          */
    PORT_HERC_COMPATIBILITY,                                    /*          */
    &VDMData.regHercCompatibility,                              /*          */
    &VDMData.regHercCompatibility,                              /*          */
    WRITE_MANY | READ_NONE | R_NE_W,                            /*          */
    aiohHercCompatibility,                                      /*          */
  },                                                            /*          */
  0,                                                            /*          */
  NULL,                                                         /*          */
};                                                              /*          */

#endif /* !CGA */                                               /*          */

#ifndef MONO

PLE pleCGAColor =                                               /*          */
{
  {                                                             /*          */
    PORT_CGACOLOR,
    &VDMData.regColor,
    &VDMData.regColor,
    WRITE_MANY | READ_MANY | R_EQ_W,                            /*          */
    aiohCGAColor,                                               /*          */
  },                                                            /*          */
  0,
  NULL,
};

PLE pleCGALPenSet =                     /* 03b9 */              /*          */
{                                                               /*          */
  {                                                             /*          */
    PORT_CGALPENSET,                                            /*          */
    NULL,                                                       /*          */
    NULL,                                                       /*          */
    WRITE_MANY | READ_MANY | R_EQ_W,                            /*          */
    aiohCGAUnknown,                                             /*          */
  },                                                            /*          */
  0,                                                            /*          */
  NULL,
};

PLE pleCGALPenReset =                   /* 03bb */              /*          */
{                                                               /*          */
  {                                                             /*          */
    PORT_CGALPENRESET,                                          /*          */
    NULL,                                                       /*          */
    NULL,                                                       /*          */
    WRITE_MANY | READ_MANY | R_EQ_W,                            /*          */
    aiohCGAUnknown,                                             /*          */
  },                                                            /*          */
  0,                                                            /*          */
  NULL,
};

#endif /* !MONO */

SCGAINFO sCGAAdapterInfo;               /* Forward */           /*          */

#ifdef MONOCGA                                                  /*          */
PSADAPTERINFO psCurAdapterInfo = &sCGAAdapterInfo;              /*          */
#else /* MONOCGA */                                             /*          */
extern PSADAPTERINFO psCurAdapterInfo;                          /*          */
#endif /* MONOCGA */                                            /*          */

#pragma  END_SWAP_DATA

#pragma  BEGIN_SWAP_CODE

/***************************************************************************
 *
 * FUNCTION NAME = vvCGAAdjustedPort()
 *
 * 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         = psTrapRegInfo contains port #
 *
 * OUTPUT        = port (possibly unchanged)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

PORT PRIVENTRY vvCGAAdjustedPort(
  PSTRAPREGINFO psTrapRegInfo )
{
  return( psTrapRegInfo->portTrap );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAOddEvenMode
 *
 * DESCRIPTION   = Get CGA odd even mode
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = True = 320x200 graphics mode
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL PRIVENTRY vvCGAOddEvenMode(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

#ifdef MONO                                                     /*          */
  return( FALSE );                                              /*          */
#else /* MONO */                                                /*          */
  return( (pvd->regMode & CGAMODE_320X200)
          >> ZEROBITS( CGAMODE_320X200 ) );                     /*          */
#endif /* MONO */                                               /*          */
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAHighResMode
 *
 * DESCRIPTION   = Get CGA high res mode
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = True = 640x200 graphics mode
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

BOOL PRIVENTRY vvCGAHighResMode(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

#ifdef MONO
  return( FALSE );
#else /* MONO */
  return( (pvd->regMode & CGAMODE_640X200)
          >> ZEROBITS( CGAMODE_640X200 ) );
#endif /* MONO */
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAStartAddr
 *
 * DESCRIPTION   = Get Display frame start address
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = offset into VRAM for display frame
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

ULONG PRIVENTRY vvCGAStartAddr(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  return(  pvd->aregCRTData [REG_CRTSTARTADDRLO]
           | (pvd->aregCRTData [REG_CRTSTARTADDRHI] << 8) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAHorzDspEnd
 *
 * DESCRIPTION   = Get Horizontal Display Width
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Horizontal Display Width
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

USHORT PRIVENTRY vvCGAHorzDspEnd(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  return( pvd->aregCRTData[REG_CRTHORZDSPEND] );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAVertDspEnd
 *
 * DESCRIPTION   = Get Vertical Display Length
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Vertical Display Length
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

USHORT PRIVENTRY vvCGAVertDspEnd(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  return( pvd->aregCRTData [REG_CRTVERTTOTAL]
          * ((pvd->aregCRTData [REG_CRTMAXSCAN] & 0x1F) + 1) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAVertLineCmp
 *
 * DESCRIPTION   = Get Vertical Display Compare
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Vertical Line Compare (for split screen)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

USHORT PRIVENTRY vvCGAVertLineCmp(
  HVDM hvdm )
{
  return( vvCGAVertDspEnd( hvdm ) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGABitsPerPixel
 *
 * DESCRIPTION   = Get Bits Per Pixel
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Bits Per Pixel
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

USHORT PRIVENTRY vvCGABitsPerPixel(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  return( ((pvd->mstateVideo <= MEMORY_FONT)
           ? 0
           : (((PSCGAINFO)psCurAdapterInfo)->
                pbfnCGAOddEvenMode( hvdm )
              ? 2
              : 1)) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvCGAPrepareSetMode()
 *
 * DESCRIPTION   = Fix Registers & return mode number
 *
 * INPUT         = HVDM
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvInt10SetMode
 *
 **************************************************************************/

USHORT PRIVENTRY vvCGAPrepareSetMode(                           /*          */
  HVDM hvdm,
  PCRF pcrf )
{
  hvdm;

  return( AL( pcrf ) );
}

#pragma  END_SWAP_CODE

#pragma  BEGIN_SWAP_DATA                                        /*          */

SCGAINFO sCGAAdapterInfo =                                      /*          */
{
  &vvCGAAdjustedPort,
  &vvCGAStartAddr,
  &vvCGAOddEvenMode,
  &vvCGAHighResMode,
  &vvCGAHorzDspEnd,
  &vvCGAHorzDspEnd,
  &vvCGAVertDspEnd,
  &vvCGABitsPerPixel,
  &vvCGAPrepareSetMode,
};

#pragma  END_SWAP_DATA                                          /*          */
