/*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 = VVVIDEO7.C
 *
 * DESCRIPTIVE NAME = Virtual Video Video7 Specific Processing
 *
 *
 * VERSION = V2.1
 *
 * DATE      04/30/93
 *
 * DESCRIPTION  This module contains all accelerator specific SVGA code 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
#define  INCL_DOSERRORS
#include <bseerr.h>

#pragma  BEGIN_SWAP_DATA
/*
**     Externals
*/
extern ULONG ulSVGAChipType;
extern SA8514INFO sA8514Info;
extern PLE pleSEQIndx;                                          /*          */
extern PLE pleSEQData;                                          /*          */
extern PLE pleMiscOutWrite;                                     /*          */
extern PLE pleGDCPos1;                                          /*          */

CHAR pszVideo7AdapterName [] = "VIDEO7" ;                       /*          */

PCHAR ppszVideo7ChipNames [MAX_VIDEO7_CHIP] =                   /*          */
{  /* As produced by SVGA.EXE! */                               /*          */
  "HT205",
  "HT208",
  "HT209",
};                                                              /*          */

RLE rleVideo7MemSEQFC =                                         /*          */
{ /* See vvVideo7PackedMode below */
  &pleSEQData,                          /* 0x03c5h (R/W) */
  PORTF_NOTVALIDSVGAPORT,               /* Not required */
  0xfc, 0x00,
  0x00,                                 /* No conditions */
  0xff,
  {0x00, 0x00, 0x00, 0x00},
  NULL,
  NULL,
};

#pragma  END_SWAP_DATA

#pragma  BEGIN_SWAP_CODE
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7EditTables()
 *
 * DESCRIPTION   = Called once to do SVGA-specific initialisation
 *
 * INPUT         =
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 **************************************************************************/

VOID PRIVENTRY vvVideo7EditTables( VOID )
{
  /* fSVGASeqFixups = TRUE; */ /* Default! */                   /*          */
  rleVideo7MemSEQFC.rle_flags &= ~PORTF_NOTVALIDSVGAPORT;       /*          */
  /*
  **  Note:
  **  We ensure here that VVWriteMiscOutFgnd doesn't get
  **  hooked for VIDEO7. The fix for IBM h/ware causes screen
  **  disturbances on the HT208/HT209 chipsets.
  */
  pleMiscOutWrite.sTrapBRegInfo.piohTrap->                      /*          */
    ioh_pbohByteOutput = NULL;                                  /*          */
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7PackedMode
 *
 * DESCRIPTION   = Get SVGA packed pixel mode.
 *
 *                 This req'd because the GDC Mode reg doesn't reflect
 *                 256-colour modes.
 *
 *                 ATI has bits in extended 'ATI registers'.
 *                 Video7 have bits in extended sequencer 0xfc.
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = True = 256 colour mode
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 * REMARK: More on the fault hook processing...
 *         Page mapping depends on the state evaluated from the
 *         shadow registers,
 *         which has to represent the true state of the hardware.
 *         If the register is not added to the aprleMemory structure,
 *         its shadow value represents the true state
 *         only after the mode set has returned,
 *         when vvUpdateAll will refresh them all.
 *         If the page mappings are believed to be       at that time,
 *         they will be invalidated and fault hooks enabled again.
 *         However, if evaluating 256-color (i.e. packed) mode
 *         is essential before the mode set returns,
 *         ensure that the register which is being evaluated is added
 *         to the aprleMemory struc.
 *
 ****************************************************************************/

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

  return( vvEGAPackedMode( hvdm )
          || (pvd->aregSEQData [0xfc] & 0x04) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7Interlaced
 *
 * DESCRIPTION   = Get Interlaced Status
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = True = interlacing on
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  /*!!Does this explain the following fixup?! */                /*          */
//  case VIDEO7_ADAPTER:            /*                             */
//    if (pvd->vvMode.vvm_nRows == 384)
//        pvd->vvMode.vvm_nRows *= 2;
//    }
  return( (pvd->aregSEQData [0xe0] & 0x01)                      /*          */
          >> ZEROBITS( 0x01 ) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7StartAddr
 *
 * DESCRIPTION   = Get Display frame start address
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = offset into VRAM for display frame
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  return(  vvCGAStartAddr( hvdm )
           | ((pvd->aregSEQData [0x1e] & 0x20)                  /*          */
              >> ZEROBITS( 0x20) << 16) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7HorzDspEnd
 *
 * DESCRIPTION   = Get Horizontal Display Length
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Horizontal Display Length
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  return( vvEGAHorzDspEnd( hvdm )
          + (((pvd->aregSEQData [0xc9] & 0x02)                  /*          */
              && (pvd->aregSEQData [0xe0] & 0x02))              /*          */
             << 8) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7PrepareSetMode()
 *
 * DESCRIPTION   = Fix Registers & return mode number
 *
 * INPUT         = HVDM
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvInt10SetMode
 *
 **************************************************************************/

USHORT PRIVENTRY vvVideo7PrepareSetMode(
  HVDM hvdm,
  PCRF pcrf )
{
  return( (AX( pcrf ) == 0x6f05)
          ? BL( pcrf )
          : vvVGAPrepareSetMode( hvdm,
                                 pcrf ) );
}

/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7SetBank()
 *
 * DESCRIPTION   = Set video7 bank register
 *
 *                 We have two scenarios here, one for the HT205 chip
 *                 (Version 3) and another for HT208/HT209 (Version 4/5)
 *                 chips.
 *
 *                 Version 4/5 are easy, a single register is dedicated to
 *                 selecting the read bank and another to the write bank.
 *                 The chip should first be set into single bank mode before
 *                 setting these registers.
 *
 *                 Version 3 chips are a nightmare.  There are different
 *                 registers to be set according to whether the mode is
 *                 16/256 colour and also for read/write bank selection.
 *
 * INPUT         = hvdm
 *                 ulBank
 *                 fSetWriteBank
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvVideo7SetBank(
  HVDM hvdm,
  ULONG ulBank,
  BOOL fSetWriteBank )
{
  register BYTE bBank,bTmp;
  BOOL fColours16;
  PVDMDATA pvd = pVDMData(hvdm);
  BYTE bSeqIndex;


                                        /*            save before lock */
  bSeqIndex = vvInput( hvdm,                                    /*          */
                       &pleSEQIndx );   /* save seq index */    /*          */
  fColours16 = !((pvd->aregSEQData [REG_SEQMEMMODE] & SEQMEM_CHAIN4)
                 && (pvd->aregSEQData [0xfc] & 0x04) );
  if( fColours16 )
  {
    /*
    ** 16-colour bank select
    */
    vvOutput( hvdm,                                             /*          */
              &pleSEQIndx,                                      /*          */
              0xf6 );                   /* select Bank Select Reg  */
    bTmp = vvInput( hvdm,                                       /*          */
                    &pleSEQData )       /* get contents       *//*          */
           & 0xf0;                      /*            reset bits 0,1*/
                                        /* for write and 2,3 for read*/
    bBank = (BYTE)(ulBank & 0x01);      /* only 1 legal bit        */
//    if (!fSetWriteBank)
//      bBank <<= 2;                    /* shift for read bank     */
                                        /*            */
    bBank = (bBank << 2) | bBank;       /* set  read=write bank     */
    bBank |= bTmp;
    vvOutput( hvdm,                                             /*          */
              &pleSEQData,                                      /*          */
              bBank );                  /* set the bank       */
  }
  else
    /*
    ** 256 colour bank select
    */
    switch( ulSVGAChipType )
    {
      case VIDEO7_HT205_CHIP :          /* Version 3 chip     */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xf9 );               /* Extended Page Sel  */
        bBank = (BYTE)(ulBank & 0x01);  /* get 1st bit        */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQData,                                  /*          */
                  bBank );              /* set this one       */
        bTmp = vvInput( hvdm,                                   /*          */
                        &pleGDCPos1 )   /* Misc Output Reg    *//*          */
               & 0xdf;                  /* clear bit 5        */
        bBank = (BYTE)(ulBank & 0x02);  /* get 2nd bit        */
        bBank <<= 4;                    /* move to bit 5      */
        vvOutput( hvdm,                                         /*          */
                  &pleMiscOutWrite,                             /*          */
                  (BYTE) (bBank | bTmp) ); /* new Misc Output */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xf6 );               /* Bank Select Reg    */
        bTmp = vvInput( hvdm,                                   /*          */
                        &pleSEQData );  /* get current value  *//*          */
        bBank = (BYTE)(ulBank);         /* get 3rd bit        */
        if( fSetWriteBank )
        {
          bTmp &= 0xfc;                 /* clear bits 0-1     */
          bBank = (bBank >> 2) & 0x03;  /* isolate bits 0-1   */
        }
        else
        {
          bTmp &= 0xf3;                 /* clear bits 3-2     */
          bBank &= 0x0c;                /* isolate bits 3-2   */
        }
        vvOutput( hvdm,                                         /*          */
                  &pleSEQData,                                  /*          */
                  (BYTE) (bBank | bTmp) ); /* set the bank    */
        break;
      case  VIDEO7_HT208_CHIP :         /* these are Version 4/5 chips */
      case  VIDEO7_HT209_CHIP :
                                        /* first set single bank mode */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xe0 );               /* Misc Control Reg   */
        bTmp = vvInput( hvdm,                                   /*          */
                        &pleSEQData)                            /*          */
               &0x7f;                   /* clear bit 7 */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQData,                                  /*          */
                  bTmp );               /* single bank mode   */
        bBank = (BYTE)ulBank << 4;      /* adjust for 64k     */

        if( pvd->mstateVideo < MEMORY_GRFX )
          bBank |= 0x20;
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xe8 );               /* Write Bank Select  */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQData,                                  /*          */
                  bBank );              /* set the bank       */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xe9 );               /* Read Bank Select   */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQData,                                  /*          */
                  bBank );              /* set the bank       */
        break;
    }
  vvOutput( hvdm,                                               /*          */
            &pleSEQIndx,                /*            */        /*          */
            bSeqIndex );                /* restore SEQ index */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7GetBank()
 *
 * DESCRIPTION   = Get Video7 bank register
 *
 * INPUT         = hvdm
 *                 fGetWriteBank
 *
 * OUTPUT        = ulBank
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvVideo7GetBank
 *
 ****************************************************************************/

ULONG PRIVENTRY vvVideo7GetBank(
  HVDM hvdm,
  BOOL fGetWriteBank )
{
  ULONG ulBank;
  BYTE bSeqIndex,bTmp;
  BOOL fColours16;
  PVDMDATA pvd = pVDMData(hvdm);
  BOOL bPrevUnlock;                                             /*          */

  /* vvUnLockSVGARegisters(); */                                /*          */
  /* Add locks again, but this time, PUSH! */                   /*          */
  bPrevUnlock = vvSVGALockPushState( hvdm );                    /*          */
  bSeqIndex = vvInput( hvdm,                                    /*          */
                       &pleSEQIndx );   /* save SEQ index    */ /*          */
  switch( ulSVGAChipType )
  {
    case  VIDEO7_HT205_CHIP :                    /* Version 3 chip          */
    case  VIDEO7_HT208_CHIP :                    /* these are Version 4/5
                                                    chips                   */
      /*!!Does not parallel setmode,looks like one is wrong!  *//*          */
      fColours16 = !((pvd->aregSEQData [REG_SEQMEMMODE] & SEQMEM_CHAIN4)
                     && (pvd->aregGDCData [REG_GDCMODE] & GDCMODE_256COLOR) );
      if( fColours16 )
      {
        /*
        ** 16-colour bank select
        */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xf6 );               /* select Bank Select */
        ulBank = vvInput( hvdm,                                 /*          */
                          &pleSEQData );/* get contents */      /*          */
        if( !fGetWriteBank )
          ulBank >>= 2;                 /* read bank bits 2-3 */
        ulBank &= 0x03;
      }
      else
      {
        /*
        ** 256 colour bank select
        */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xf9 );               /* Extended Page Sel  */
        ulBank = vvInput( hvdm,                                 /*          */
                          &pleSEQData )                         /*          */
                 & 0x01;                /* get bit 0 */
        ulBank |= (vvInput( hvdm,                               /*          */
                            &pleGDCPos1 )                       /*          */
                   & 0x20) >> 4;        /* Misc Out:5 is :1   */
        vvOutput( hvdm,                                         /*          */
                  &pleSEQIndx,                                  /*          */
                  0xf6 );               /* Bank Select Reg    */
        bTmp = vvInput( hvdm,                                   /*          */
                        &pleSEQData );  /* get Bank Select    *//*          */
        if( fGetWriteBank )
          bTmp <<= 2;
        bTmp &= 0x0c;                   /* isolate bits 2-3   */
        ulBank |= (ULONG)bTmp;          /* combine            */
      }
      break;
    case  VIDEO7_HT209_CHIP :                                   /*          */
      vvOutput( hvdm,                                           /*          */
                &pleSEQIndx,                                    /*          */
                (BYTE) (fGetWriteBank                           /*          */
                        ? 0xe8          /* Write Bank Select  *//*          */
                        : 0xe9 ) );     /* Read Bank Select   *//*          */
      ulBank = vvInput( hvdm,                                   /*          */
                        &pleSEQData )                           /*          */
               >> 4;                    /* get bank           */
      if( pvd->mstateVideo < MEMORY_GRFX )
        ulBank &= ~0x02;
      break;
  }
  vvOutput( hvdm,                                               /*          */
            &pleSEQIndx,                                        /*          */
            bSeqIndex );                /* restore SEQ index */ /*          */
  /* Add locks again, but this time, POP! */                    /*          */
  vvSVGALockPopState( hvdm, bPrevUnlock );                      /*          */
  return( ulBank & 0x0f );
}

/***************************************************************************
 *
 * FUNCTION NAME = vvVideo7FixSetMode()
 *
 * DESCRIPTION   = Fix Video7 text registers
 *
 *                 When BIOS sets 132 column modes, it sets the extended
 *                 register 0xFD (Timing Select) to a typical value of 0xcd
 *                 when read. If we blindly save and then restore this value,
 *                 the timing is incorrect. The lower nibble of this byte
 *                 determines text mode timings, and is usually set to 2.
 *                 On completion of a mode set, we get called here and reset
 *                 the register to 2. (I've consulted Headland Technology
 *                 and they confirmed the value )
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *
 ****************************************************************************/

VOID PRIVENTRY vvVideo7FixSetMode(
  HVDM hvdm,
  ULONG ulMode )
{
  BYTE bSeqIndex;

  ulMode;
  if( VDMBase.rb_nVCols == 132 )
  {                                     /* Only extended text mode */
    bSeqIndex = vvInput( hvdm,
                         &pleSEQIndx );
    vvOutput( hvdm,                     /* start synch reset       */
              &pleSEQIndx,
              0x00 );
    vvOutput( hvdm,
              &pleSEQData,
              0x00 );
    vvOutput( hvdm,                     /* set text timing         */
              &pleSEQIndx,
              0xfd );
    vvOutput( hvdm,
              &pleSEQData,
              0x02 );
    vvOutput( hvdm,                     /* end synch reset         */
              &pleSEQIndx,
              0x00 );
    vvOutput( hvdm,
              &pleSEQData,
              0x03 );
    vvOutput( hvdm,
              &pleSEQIndx,
              bSeqIndex );
  }
}

#pragma  END_SWAP_CODE

#pragma  BEGIN_SWAP_DATA

SSVGAINFO sVideo7AdapterInfo =                                  /*          */
{
  { /* SVGAINFO */                                              /*          */
    { /* SEGAINFO */
      { /* SCGAINFO */
        &vvEGAAdjustedPort,
        &vvCGAStartAddr,
        &vvEGAOddEvenMode,
        &vvEGAHighResMode,
        &vvVideo7HorzDspEnd,
        &vvEGAHorzLogEnd,                                       /*            */
        &vvVGAVertDspEnd,
        &vvVGABitsPerPixel,
        &vvVideo7PrepareSetMode,                                /*          */
      },
      &vvVideo7PackedMode,
      &vvVGAVertLineCmp,
    },
    &vvVGADacSave,                                              /*          */
    &vvVGADacRestore,                                           /*          */
  },                                                            /*          */
  &vvVideo7EditTables,
  &vvVGAInterlaced,
  &vvVGAUpdateIoState,
  &vvVGARestoreIoState,
  &vvVideo7SetBank,
  &vvVideo7GetBank,
  &vvVideo7FixSetMode,
  &vvVGAFixSetBgnd,
  &vvVGAWriteGDCDataFgnd,
  &vvVGAReadSEQDataBgnd,
  &vvVGAWriteSEQDataBgnd,
  &vvVGADacRS2Clear,                                            /*          */
  &vvVGADacRS2Set,                                              /*          */
  &vvVGADacRS3,                                                 /*          */
  NULL,                                                         /*           */
  pszVideo7AdapterName,
  MAX_VIDEO7_CHIP,
  ppszVideo7ChipNames,
  NULL,                                                         /*           */
};

#pragma  END_SWAP_DATA
