/*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 = VVATI.C
 *
 * DESCRIPTIVE NAME = Virtual Video ATI 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 IOH iohA8514wreg [2];                                    /*          */
extern IOH iohA8514mfreg [2];                                   /*          */
extern IOH aiohVGADACMask [2];          /* 0x03c6 */            /*          */
extern IOH aiohVGADACRead [2];          /* 0x03c7 */            /*          */
extern IOH aiohVGADACWrite [2];         /* 0x03c8 */            /*          */
extern IOH aiohVGADACData [2];          /* 0x03c9 */            /*          */
extern PSACCELERATORINFO psCurAcceleratorInfo;                  /*          */
extern PSDACINFO psCurDacInfo;                                  /*          */
extern PPLE ppleDacExtMask;                                     /*          */
extern PPLE ppleDacExtRead;                                     /*          */
extern PPLE ppleDacExtWrite;                                    /*          */
extern PPLE ppleDacExtData;                                     /*          */
extern STRAPREGPARTINFO sTrapWRegLow;                           /*          */
extern STRAPREGPARTINFO sTrapWRegHigh;                          /*          */
extern STRAPREGPARTINFO sTrapWRegWhole;                         /*          */
extern PVDM  pvdmStartupMMIOActive;                                            /*            */
extern ULONG npgStartupMMIOActive;                                             /*            */

/*
**     Locals
*/

CHAR pszATIAdapterName [] = "ATI";                              /*          */

PCHAR ppszATIChipNames [MAX_ATI_CHIP] =                         /*          */
{  /* As produced by SVGA.EXE! */                               /*          */
  ATI_18800_NAME,                                               /*          */
  ATI_28800_NAME,                                               /*          */
  ATI_38800_NAME,                                               /*          */
  ATI_68800_NAME,                                               /*          */
  ATI_88800_NAME,                                               /*          */
};                                                              /*          */

IOH aiohATIVGAIndx [2] =                /* 01ce */
{
  {
    NULL,
  },
  {
    &VVReadATIIndxBgnd,
    &VVWriteATIIndxBgnd,
  },
};

IOH aiohATIVGAData [2] =                /* 01cf */
{
  {
    NULL,
  },
  {
    &VVReadATIDataBgnd,
    &VVWriteATIDataBgnd,
  },
};

IOH iohMach64wreg [2];                  /* Forward */           /*          */

 /*
 **
 **  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.
 */

BYTE abATIMask [MAX_ATIREGS] =                                  /*@V3.0YEE01*/
{
  0x00
};                                                              /*          */


 /*
 **  ATI extended registers, range 0xa0-0xbf expect some intial values to
 **  be set. This array is initialised at vvinit time.
 */

BYTE    aregATIInit [ATI_TOTAL_INITREGS];

/****************************************************************************/

PLE pleATIVGAIndx =                                             /*          */
{
  {                                                             /*          */
    PORT_ATIVGA_INDX,                   /* 1CEh (R/W) */
    &VDMData.VdmSVGA.regATIIndx,                                /*          */
    &VDMData.VdmSVGA.regATIIndx,                                /*          */
    PORTF_NOTVALIDSVGAPORT                                      /*          */
      | WRITE_MANY | READ_MANY | R_EQ_W,                        /*          */
    aiohATIVGAIndx,                                             /*          */
  },                                                            /*          */
  0,                                                            /*          */
  NULL,                                                         /*          */
  NULL,                                                         /*V2.2SEN01*/
};

PLE pleATIVGAData =                                             /*          */
{                                                               /*          */
  {                                                             /*          */
    PORT_ATIVGA_DATA,                   /* 1CFh (R/W) */        /*          */
    &VDMData.VdmSVGA.aregATIData[0],                            /*          */
    &VDMData.VdmSVGA.aregATIData[0],                            /*          */
    PORTF_NOTVALIDSVGAPORT                                      /*          */
      | WRITE_INDX | READ_INDX | R_EQ_W,                        /*          */
    aiohATIVGAData,                                             /*          */
  },                                                            /*          */
  MAX_ATIREGS,                                                  /*          */
  &pleATIVGAIndx,                                               /*          */
  &abATIMask[0],                                                /*          */
  &abATIMask[0],                                                /*V2.2SEN01*/
};

PLE pleATIDacMask =                                             /*          */
{                                                               /*          */
  {                                                             /*          */
    A8514_DACMASK,                      /* 0x02ea (R/W) */      /*          */
    &VDMData.regDACMask,                                        /*          */
    &VDMData.regDACMask,                                        /*          */
    PORTF_NOTVALIDSVGAPORT                                      /*          */
      | WRITE_MANY | READ_MANY | R_EQ_W,                        /*          */
    aiohVGADACMask,                                             /*          */
  },                                                            /*          */
  0,                                    /* non-Index register *//*          */
  NULL,                                                         /*          */
  NULL,                                                         /*          */
};                                                              /*          */

PLE pleATIDacRead =                                             /*          */
{                                                               /*          */
  {                                                             /*          */
    A8514_DACREADINDEX,                 /* 0x02eb (R/W) */      /*          */
    &VDMData.regDACIndx,                                        /*          */
    &VDMData.regDACIndx,                                        /*          */
    PORTF_NOTVALIDSVGAPORT                                      /*          */
      | WRITE_MANY | READ_NONE | R_NE_W,                        /*          */
    aiohVGADACRead,                                             /*          */
  },                                                            /*          */
  0,                                    /* non-Index register *//*          */
  NULL,                                                         /*          */
  NULL,                                                         /*          */
};                                                              /*          */

PLE pleATIDacWrite =                                            /*          */
{                                                               /*          */
  {                                                             /*          */
    A8514_DACWRITEINDEX,                /* 0x02ec (R/W) */      /*          */
    &VDMData.regDACIndx,                                        /*          */
    &VDMData.regDACIndx,                                        /*          */
    PORTF_NOTVALIDSVGAPORT                                      /*          */
      | WRITE_MANY | READ_MANY | R_EQ_W,                        /*          */
    aiohVGADACWrite,                                            /*          */
  },                                                            /*          */
  0,                                                            /*          */
  NULL,                                                         /*          */
  NULL,                                                         /*          */
};                                                              /*          */

PLE pleATIDacData =                                             /*          */
{                                                               /*          */
  {                                                             /*          */
    A8514_DACDATA,                      /* 0x02ed (R/W) */      /*          */
    &VDMData.dacDACDataCur,                                     /*          */
    &VDMData.dacDACDataCur,                                     /*          */
    PORTF_NOTVALIDSVGAPORT                                      /*          */
      | WRITE_MANY | READ_MANY | R_EQ_W,                        /*          */
    aiohVGADACData,                                             /*          */
  },                                                            /*          */
  0,                                    /* non-Index register *//*          */
  NULL,                                                         /*          */
  NULL,                                                         /*          */
};                                                              /*          */

/****************************************************************************/

RLE rleATIMemATI30 =                                            /*          */
{ /* See vvATIPackedMode below */                               /*          */
  &pleATIVGAData,
  PORTF_NOTVALIDSVGAPORT | PORTF_REQUIRED,                       /* 1CFh (R/W)            */
  0xb0, 0,
  0,
//  0xf6,                            
  0x20,                                                         /*@V3.0MNH03*/
  {0x00,0x00,0x00,0x20},                                        /*@V3.0MNH03*/
//@V3.0MNH03  0x21,                  //          
//            {0x08,0x08,0x09,0x28},
//@V3.0MNH03  {0x00,0x00,0x01,0x20}, //          
  NULL,
  NULL,
};

/****************************************************************************/

/*
** Write many registers are ones which writing many times with the
** same value generally has the same result as writing them only once.
**
** Write once registers are ones which usually expect a stream of
** values where each value is used only once, perhaps deposited or XORed
** somewhere in VRAM, such as pixel bytes and stroke drawing regs.
**
** Read once registers are similar to write once registers.
** They usually are a stream of values extracted from VRAM.
**
** Read many registers are simliar to write many registers.
** These are the ones which reading many times usually gets the same value
** as the first (unless some asynchronous status changes).
*/

/*
** To quote ATI "Programmers Guide to the Mach 32 Registers" page 8-16:
** "I/O Address bit A14 if set has the effect of adding wait states
** to any read or write operation that would otherwise cause
** SUBSYS_STAT[2] to be set if executed immediately."
*/

#define ATIMACH32TRAPREGSIZE 0x80
#define WS(x) ((PVOID)(&VDMData.VdmSVGA.wRegShadow [x]))

STRAPREGINFO sATIMach32TrapRegInfo [ATIMACH32TRAPREGSIZE] =
{
  {/*x00*/0x02e8, WS(0x00), WS(0x80), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x01*/0x02ee, WS(0x01), WS(0x81), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x02*/0x06e8, WS(0x02), WS(0x82), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x03*/0x06ee, WS(0x03), WS(0x83), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x04*/0x0ae8, WS(0x04), WS(0x84), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x05*/0x0aee, WS(0x05), WS(0x85), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x06*/0x0ee8, WS(0x06), WS(0x86), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x07*/0x0eee, WS(0x07), WS(0x87), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x08*/0x12e8, WS(0x08), WS(0x88), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x09*/0x12ee, WS(0x09), WS(0x89), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x0a*/0x16e8, WS(0x0a), WS(0x8a), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x0b*/0x16ee, WS(0x0b), WS(0x8b), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x0c*/0x1ae8, WS(0x0c), WS(0x8c), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x0d*/0x1aee, WS(0x0d), WS(0x8d), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x0e*/0x1ee8, WS(0x0e), WS(0x8e), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x0f*/0x1eee, WS(0x0f), WS(0x8f), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x10*/0x22e8, WS(0x10), WS(0x90), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x11*/0x22ee, WS(0x11), WS(0x91), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x12*/0x26e8, WS(0x12), WS(0x92), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x13*/0x26ee, WS(0x13), WS(0x93), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x14*/0x2ae8, WS(0x14), WS(0x94), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x15*/0x2aee, WS(0x15), WS(0x95), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x16*/0x2ee8, WS(0x16), WS(0x96), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x17*/0x2eee, WS(0x17), WS(0x97), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x18*/0x32e8, WS(0x18), WS(0x98), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x19*/0x32ee, WS(0x19), WS(0x19), WRITE_MANY | READ_MANY | R_EQ_W, iohA8514wreg } , /*@V3.0MNH02*/
  {/*x1a*/0x36e8, WS(0x1a), WS(0x9a), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x1b*/0x36ee, WS(0x1b), WS(0x1b), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } , /* Mach 8 = R/O */
  {/*x1c*/0x3ae8, WS(0x1c), WS(0x9c), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x1d*/0x3aee, WS(0x1d), WS(0x9d), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x1e*/0x3ee8, WS(0x1e), WS(0x9e), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x1f*/0x3eee, WS(0x1f), WS(0x9f), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x20*/0x42e8, WS(0x20), WS(0xa0), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x21*/0x42ee, WS(0x21), WS(0x21), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  /* 0x46e8 already handled with pleVSE */                                             /*          */
  {/*x22*/0x46e8, WS(0x22), WS(0x22), NONE       | NONE      | NONE  , iohA8514wreg} , /*          */
  {/*x23*/0x46ee, WS(0x23), WS(0xa3), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x24*/0x4ae8, WS(0x24), WS(0xa4), WRITE_MANY | NONE      | R_NE_W | PORT_STAYS_HOOKED, iohA8514wreg } ,/*V2.2SEN01*/
  {/*x25*/0x4aee, WS(0x25), WS(0x25), WRITE_MANY | READ_MANY | R_EQ_W, iohA8514wreg } , /*@V3.0MNH02*/
  {/*x26*/0x4ee8, WS(0x26), WS(0xa6), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x27*/0x4eee, WS(0x27), WS(0xa7), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x28*/0x52e8, WS(0x28), WS(0xa8), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x29*/0x52ee, WS(0x29), WS(0x29), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x2a*/0x56e8, WS(0x2a), WS(0xaa), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x2b*/0x56ee, WS(0x2b), WS(0x2b), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x2c*/0x5ae8, WS(0x2c), WS(0xac), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x2d*/0x5aee, WS(0x2d), WS(0xad), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x2e*/0x5ee8, WS(0x2e), WS(0xae), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x2f*/0x5eee, WS(0x2f), WS(0x2f), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x30*/0x62e8, WS(0x30), WS(0xb0), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x31*/0x62ee, WS(0x31), WS(0xb1), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x32*/0x66e8, WS(0x32), WS(0xb2), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x33*/0x66ee, WS(0x33), WS(0xb3), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x34*/0x6ae8, WS(0x34), WS(0xb4), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x35*/0x6aee, WS(0x35), WS(0x35), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x36*/0x6ee8, WS(0x36), WS(0xb6), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x37*/0x6eee, WS(0x37), WS(0xb7), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x38*/0x72e8, WS(0x38), WS(0xb8), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x39*/0x72ee, WS(0x39), WS(0xb9), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x3a*/0x76e8, WS(0x3a), WS(0xba), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x3b*/0x76ee, WS(0x3b), WS(0xbb), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x3c*/0x7ae8, WS(0x3c), WS(0xbc), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x3d*/0x7aee, WS(0x3d), WS(0xbd), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x3e*/0x7ee8, WS(0x3e), WS(0xbe), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
//          
//  {/*x3f*/0x7eee, WS(0x3f), WS(0xbf), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x3f*/0x7eee, WS(0x3f), WS(0xbf), WRITE_ONCE | READ_MANY | R_NE_W, iohA8514wreg } , //          
  {/*x40*/0x82e8, WS(0x40), WS(0x40), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x41*/0x82ee, WS(0x41), WS(0x41), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x42*/0x86e8, WS(0x42), WS(0x42), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x43*/0x86ee, WS(0x43), WS(0xc3), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x44*/0x8ae8, WS(0x44), WS(0xc4), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x45*/0x8aee, WS(0x45), WS(0xc5), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x46*/0x8ee8, WS(0x46), WS(0xc6), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x47*/0x8eee, WS(0x47), WS(0x3d), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x48*/0x92e8, WS(0x48), WS(0x48), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x49*/0x92ee, WS(0x49), WS(0x3f), NONE       | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x4a*/0x96e8, WS(0x4a), WS(0xca), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x4b*/0x96ee, WS(0x4a), WS(0x4a), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } , /*Same as 96e8!*/
  {/*x4c*/0x9ae8, WS(0x4c), WS(0xcc), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x4d*/0x9aee, WS(0x4d), WS(0xcd), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x4e*/0x9ee8, WS(0x4e), WS(0xce), WRITE_ONCE | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x4f*/0x9eee, WS(0x4f), WS(0xcf), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x50*/0xa2e8, WS(0x50), WS(0xd0), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x51*/0xa2ee, WS(0x51), WS(0x51), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x52*/0xa6e8, WS(0x52), WS(0xd2), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x53*/0xa6ee, WS(0x53), WS(0xd3), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x54*/0xaae8, WS(0x54), WS(0xd4), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x55*/0xaaee, WS(0x55), WS(0xd5), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x56*/0xaee8, WS(0x56), WS(0xd6), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x57*/0xaeee, WS(0x57), WS(0xd7), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x58*/0xb2e8, WS(0x58), WS(0xd8), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x59*/0xb2ee, WS(0x59), WS(0x02), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x5a*/0xb6e8, WS(0x5a), WS(0xda), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x5b*/0xb6ee, WS(0x5b), WS(0x04), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x5c*/0xbae8, WS(0x5c), WS(0xdc), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x5d*/0xbaee, WS(0x5d), WS(0x06), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x5e*/0xbee8, WS(0x5e), WS(0xde), WRITE_INDX | NONE      | R_NE_W, iohA8514mfreg } ,
  {/*x5f*/0xbeee, WS(0x5f), WS(0xdf), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x60*/0xc2e8, WS(0x60), WS(0xe0), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x61*/0xc2ee, WS(0x61), WS(0x08), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x62*/0xc6e8, WS(0x62), WS(0xe2), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x63*/0xc6ee, WS(0x63), WS(0x0a), WRITE_ONCE | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x64*/0xcae8, WS(0x64), WS(0xe4), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x65*/0xcaee, WS(0x65), WS(0x0c), WRITE_ONCE | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x66*/0xcee8, WS(0x66), WS(0xe6), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x67*/0xceee, WS(0x67), WS(0xe7), NONE       | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x68*/0xd2e8, WS(0x68), WS(0xe8), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x69*/0xd2ee, WS(0x69), WS(0x0e), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x6a*/0xd6e8, WS(0x6a), WS(0xea), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x6b*/0xd6ee, WS(0x6b), WS(0x6b), WRITE_MANY | READ_MANY | NONE  , iohA8514wreg } ,
  {/*x6c*/0xdae8, WS(0x6c), WS(0xec), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x6d*/0xdaee, WS(0x6d), WS(0x46), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x6e*/0xdee8, WS(0x6e), WS(0xee), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x6f*/0xdeee, WS(0x6f), WS(0x44), WRITE_MANY | READ_MANY | R_NE_W, iohA8514wreg } ,
  {/*x70*/0xe2e8, WS(0x70), WS(0x50), WRITE_ONCE | READ_ONCE | R_NE_W, iohA8514wreg } , /* Only when not drawing!*/
  {/*x71*/0xe2ee, WS(0x71), WS(0xf1), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x72*/0xe6e8, WS(0x72), WS(0x52), WRITE_ONCE | READ_ONCE | R_NE_W, iohA8514wreg } , /* Only when not drawing!*/
  {/*x73*/0xe6ee, WS(0x73), WS(0xf3), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x74*/0xeae8, WS(0x74), WS(0xf4), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x75*/0xeaee, WS(0x75), WS(0xf5), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x76*/0xeee8, WS(0x76), WS(0xf6), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x77*/0xeeee, WS(0x77), WS(0xf7), WRITE_MANY | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x78*/0xf2e8, WS(0x78), WS(0xf8), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x79*/0xf2ee, WS(0x79), WS(0xf9), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x7a*/0xf6e8, WS(0x7a), WS(0xfa), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x7b*/0xf6ee, WS(0x7b), WS(0xfb), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x7c*/0xfae8, WS(0x7c), WS(0xfc), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x7d*/0xfaee, WS(0x7d), WS(0xfd), NONE       | READ_MANY | R_NE_W, iohA8514wreg } , /*@V3.0MNH02*/
  {/*x7e*/0xfee8, WS(0x7e), WS(0xfe), NONE       | NONE      | R_NE_W, iohA8514wreg } ,
  {/*x7f*/0xfeee, WS(0x7f), WS(0xff), WRITE_ONCE | NONE      | R_NE_W, iohA8514wreg } ,
};

#define ATIMACH64TRAPREGSIZE 0x40                                /*          */
#define RW_MANY (WRITE_MANY | READ_MANY | R_EQ_W)                /*          */
#define RO_MANY (WRITE_NONE | READ_MANY | R_NE_W)                /*          */
#define NO_MANY (WRITE_NONE | READ_NONE | R_NE_W)                /*          */

STRAPREGINFO sATIMach64TrapRegInfo [ATIMACH64TRAPREGSIZE] =      /*          */
{
  {/*x00*/0x02ec, WS(0x00), WS(0x00), RW_MANY, iohMach64wreg }, /*          */
  {/*x01*/0x02ee, WS(0x01), WS(0x01), RW_MANY, iohMach64wreg }, /*          */
  {/*x02*/0x06ec, WS(0x02), WS(0x02), RW_MANY, iohMach64wreg }, /*          */
  {/*x03*/0x06ee, WS(0x03), WS(0x03), RW_MANY, iohMach64wreg }, /*          */
  {/*x04*/0x0aec, WS(0x04), WS(0x04), RW_MANY, iohMach64wreg }, /*          */
  {/*x05*/0x0aee, WS(0x05), WS(0x05), RW_MANY, iohMach64wreg }, /*          */
  {/*x06*/0x0eec, WS(0x06), WS(0x06), RW_MANY, iohMach64wreg }, /*          */
  {/*x07*/0x0eee, WS(0x07), WS(0x07), RW_MANY, iohMach64wreg }, /*          */
  {/*x08*/0x12ec, WS(0x08), WS(0x08), RW_MANY, iohMach64wreg }, /*          */
  {/*x09*/0x12ee, WS(0x09), WS(0x09), RW_MANY, iohMach64wreg }, /*          */
  {/*x0a*/0x16ec, WS(0x0a), WS(0x0a), RW_MANY, iohMach64wreg }, /*          */
  {/*x0b*/0x16ee, WS(0x0b), WS(0x0b), RW_MANY, iohMach64wreg }, /*          */
  {/*x0c*/0x1aec, WS(0x0c), WS(0x0c), RW_MANY, iohMach64wreg }, /*          */
  {/*x0d*/0x1aee, WS(0x0d), WS(0x0d), RW_MANY, iohMach64wreg }, /*          */
  {/*x0e*/0x1eec, WS(0x0e), WS(0x0e), RW_MANY, iohMach64wreg }, /*          */
  {/*x0f*/0x1eee, WS(0x0f), WS(0x0f), RW_MANY, iohMach64wreg }, /*          */
  {/*x10*/0x22ec, WS(0x10), WS(0x10), RW_MANY, iohMach64wreg }, /*          */
  {/*x11*/0x22ee, WS(0x11), WS(0x11), RW_MANY, iohMach64wreg }, /*          */
  {/*x12*/0x26ec, WS(0x12), WS(0x12), RW_MANY, iohMach64wreg }, /*          */
  {/*x13*/0x26ee, WS(0x13), WS(0x13), RW_MANY, iohMach64wreg }, /*          */
  {/*x14*/0x2aec, WS(0x14), WS(0x14), RW_MANY, iohMach64wreg }, /*          */
  {/*x15*/0x2aee, WS(0x15), WS(0x15), RW_MANY, iohMach64wreg }, /*          */
  {/*x16*/0x2eec, WS(0x16), WS(0x16), RW_MANY, iohMach64wreg }, /*          */
  {/*x17*/0x2eee, WS(0x17), WS(0x17), RW_MANY, iohMach64wreg }, /*          */
  {/*x18*/0x32ec, WS(0x18), WS(0x18), RW_MANY, iohMach64wreg }, /*          */
  {/*x19*/0x32ee, WS(0x19), WS(0x19), RW_MANY, iohMach64wreg }, /*          */
  {/*x1a*/0x36ec, WS(0x1a), WS(0x1a), RW_MANY, iohMach64wreg }, /*          */
  {/*x1b*/0x36ee, WS(0x1b), WS(0x1b), RW_MANY, iohMach64wreg }, /*          */
  {/*x1c*/0x3aec, WS(0x1c), WS(0x1c), RW_MANY, iohMach64wreg }, /*          */
  {/*x1d*/0x3aee, WS(0x1d), WS(0x1d), RW_MANY, iohMach64wreg }, /*          */
  {/*x1e*/0x3eec, WS(0x1e), WS(0x1e), RW_MANY, iohMach64wreg }, /*          */
  {/*x1f*/0x3eee, WS(0x1f), WS(0x1f), RW_MANY, iohMach64wreg }, /*          */
  {/*x20*/0x42ec, WS(0x20), WS(0x20), RW_MANY, iohMach64wreg }, /*          */
  {/*x21*/0x42ee, WS(0x21), WS(0x21), RW_MANY, iohMach64wreg }, /*          */
  {/*x22*/0x46ec, WS(0x22), WS(0x22), RW_MANY, iohMach64wreg }, /*          */
  {/*x23*/0x46ee, WS(0x23), WS(0x23), RW_MANY, iohMach64wreg }, /*          */
  {/*x24*/0x4aec, WS(0x24), WS(0x24), RW_MANY, iohMach64wreg }, /*          */
  {/*x25*/0x4aee, WS(0x25), WS(0x25), RW_MANY, iohMach64wreg }, /*          */
  {/*x26*/0x4eec, WS(0x26), WS(0x26), RW_MANY, iohMach64wreg }, /*          */
  {/*x27*/0x4eee, WS(0x27), WS(0x27), RW_MANY, iohMach64wreg }, /*          */
  {/*x28*/0x52ec, WS(0x28), WS(0x28), RW_MANY, iohMach64wreg }, /*          */
  {/*x29*/0x52ee, WS(0x29), WS(0x29), RW_MANY, iohMach64wreg }, /*          */
  {/*x2a*/0x56ec, WS(0x2a), WS(0x2a), RW_MANY, iohMach64wreg }, /*          */
  {/*x2b*/0x56ee, WS(0x2b), WS(0x2b), RW_MANY, iohMach64wreg }, /*          */
  {/*x2c*/0x5aec, WS(0x2c), WS(0x2c), RW_MANY, iohMach64wreg }, /*          */
  {/*x2d*/0x5aee, WS(0x2d), WS(0x2d), RW_MANY, iohMach64wreg }, /*          */
  /* DACs are trapped specially, not here */                    /*          */
  {/*x2e*/0x5eec, WS(0x2e), WS(0x2e), NO_MANY, iohMach64wreg }, /*          */
  {/*x2f*/0x5eee, WS(0x2f), WS(0x2f), NO_MANY, iohMach64wreg }, /*          */
  {/*x30*/0x62ec, WS(0x30), WS(0x30), RW_MANY, iohMach64wreg }, /*          */
  {/*x31*/0x62ee, WS(0x31), WS(0x31), RW_MANY, iohMach64wreg }, /*          */
  {/*x32*/0x66ec, WS(0x32), WS(0x32), RW_MANY, iohMach64wreg }, /*          */
  {/*x33*/0x66ee, WS(0x33), WS(0x33), RW_MANY, iohMach64wreg }, /*          */
  {/*x34*/0x6aec, WS(0x34), WS(0x34), RW_MANY, iohMach64wreg }, /*          */
  {/*x35*/0x6aee, WS(0x35), WS(0x35), RW_MANY, iohMach64wreg }, /*          */
  {/*x36*/0x6eec, WS(0x36), WS(0x76), RO_MANY, iohMach64wreg }, /*          */
  {/*x37*/0x6eee, WS(0x37), WS(0x77), RO_MANY, iohMach64wreg }, /*          */
  {/*x38*/0x72ec, WS(0x38), WS(0x78), RO_MANY, iohMach64wreg }, /*          */
  {/*x39*/0x72ee, WS(0x39), WS(0x79), RO_MANY, iohMach64wreg }, /*          */
  {/*x3a*/0x76ec, WS(0x3a), WS(0x7a), RO_MANY, iohMach64wreg }, /*          */
  {/*x3b*/0x76ee, WS(0x3b), WS(0x7b), RO_MANY, iohMach64wreg }, /*          */
  {/*x3c*/0x7aec, WS(0x3c), WS(0x3c), NO_MANY, iohMach64wreg }, /*          */
  {/*x3d*/0x7aee, WS(0x3d), WS(0x3d), NO_MANY, iohMach64wreg }, /*          */
  {/*x3e*/0x7eec, WS(0x3e), WS(0x3e), NO_MANY, iohMach64wreg }, /*          */
  {/*x3f*/0x7eee, WS(0x3f), WS(0x3f), NO_MANY, iohMach64wreg }, /*          */
};                                                              /*          */

SA8514INFO sATIMach32Info;              /* Forward */           /*          */
SACCELERATORINFO sATIMach64Info;        /* Forward */           /*          */
SSVGAINFO sATIAdapterInfo;              /* Forward */           /*          */

#pragma  END_SWAP_DATA

#pragma  BEGIN_SWAP_CODE
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIPackedMode
 *
 * 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 vvATIPackedMode(
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  return( vvEGAPackedMode( hvdm )
          || (pvd->VdmSVGA.aregATIData [0xb0]
              & ((ulSVGAChipType == ATI_18800_CHIP)             /*          */
                 ? 0x3e                 /* isolate 1:2,4:5    *//*          */
                 : 0x20)) );            /* isolate bit 5      *//*          */
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIInterlaced
 *
 * DESCRIPTION   = Get Interlaced Status
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = True = interlacing on
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  return( (pvd->VdmSVGA.aregATIData [0xbe] & 0x02)
          >> ZEROBITS( 0x02 ) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIStartAddr
 *
 * DESCRIPTION   = Get Display frame start address
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = offset into VRAM for display frame
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  return(  vvCGAStartAddr( hvdm )
           | ((pvd->VdmSVGA.aregATIData [0xb0] & 0x40)
              >> ZEROBITS( 0x40) << 16)
           | ((pvd->VdmSVGA.aregATIData [0xa3] & 0x08)
              >> ZEROBITS( 0x08) << 17)
           | ((pvd->VdmSVGA.aregATIData [0xad] & 0x0c)
              >> ZEROBITS( 0x0c) << 18) );
}
                                                                /*          */
//           ***************************************************************************
//           *
//           * FUNCTION NAME = vvATIHorzLogEnd
//           *
//           * DESCRIPTION   = Get Horizontal Logical End
//           *
//           * INPUT         = hvdm
//           *
//           * OUTPUT        = Horizontal Logical End
//           *
//           * RETURN-NORMAL =
//           * RETURN-ERROR  =
//           *
//           ****************************************************************************/
//          
//                 PRIVENTRY vvATIHorzLogEnd(
//            HVDM hvdm )
//           
//            register PVDMDATA pvd = pVDMData(hvdm);
//          
//            return( vvEGAHorzLogEnd( hvdm )
//                    << ((vvATIPackedMode( hvdm )                          /*          */
//                         && (vvEGAHorzLogEnd( hvdm ) >= 80))              /*          */
//                        << 1) );                                          /*          */
//           
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIVertDspEnd
 *
 * DESCRIPTION   = Get Vertical Display Length
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Vertical Display Length
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  return( vvVGAVertDspEnd( hvdm )
          + ((pvd->aregCRTData [0x35] & 0x04)
             >> ZEROBITS( 0x04 ) << 10) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIVertLineCmp
 *
 * DESCRIPTION   = Get Vertical Line Compare
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = Vertical Line Compare (for split screen)
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

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

  return( vvVGAVertLineCmp( hvdm )
          | ((pvd->aregCRTData [0x35] & 0x10)
             >> ZEROBITS( 0x10 ) << 10) );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach32DacRS2Clear()
 *
 * DESCRIPTION   = Reset DAC RS2
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach32DacRS2Clear(                          /*          */
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  vvOutput( INVALID_HVDM,
            &pleATIVGAIndx,
            0xa0 );                     /* ATI's key to DAC  */
  pvd->VdmSVGA.aregATIData [0xa0] &= ~ (0x01 << ZEROBITS( 0x60 ) );
  vvOutput( INVALID_HVDM,
            &pleATIVGAData,
            pvd->VdmSVGA.aregATIData [0xa0] );
  psCurDacInfo->pfnDacIPFClear( hvdm );                         /*          */
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach32DacRS2Set()
 *
 * DESCRIPTION   = Reset DAC RS2
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach32DacRS2Set(                            /*          */
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

//psCurDacInfo->pfnDacIPFSet( hvdm );                           /*          */
  vvOutput( INVALID_HVDM,
            &pleATIVGAIndx,
            0xa0 );                     /* ATI's key to DAC  */
  pvd->VdmSVGA.aregATIData [0xa0] |= (0x01 << ZEROBITS( 0x60 ) );
  vvOutput( INVALID_HVDM,
            &pleATIVGAData,
            pvd->VdmSVGA.aregATIData [0xa0] );
  /* Must be set afterwards since other outs might clear it! */ /*          */
  psCurDacInfo->pfnDacIPFSet( hvdm );                           /*          */
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach32DacRS3()
 *
 * DESCRIPTION   = Set DAC RS3 State
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach32DacRS3(                               /*          */
  HVDM hvdm,
  BOOL bRS3 )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  vvOutput( INVALID_HVDM,
            &pleATIVGAIndx,
            0xa0 );                     /* ATI's key to DAC  */
  pvd->VdmSVGA.aregATIData [0xa0] &= ~ 0x40;                    /*          */
  pvd->VdmSVGA.aregATIData [0xa0] |= bRS3 << ZEROBITS( 0x40 );
  vvOutput( INVALID_HVDM,
            &pleATIVGAData,
            pvd->VdmSVGA.aregATIData [0xa0] );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach32DacSave()
 *
 * DESCRIPTION   = Save DAC state
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach32DacSave(                              /*          */
  HVDM hvdm )
{
  BYTE bDACKey;
  register PVDMDATA pvd = pVDMData(hvdm);

  /* Add save and restore RS[3:2] */
  bDACKey = pvd->VdmSVGA.aregATIData [0xa0];
  pvd->VdmSVGA.aregATIData [0xa0] &=
    ~ (0x03 << ZEROBITS( 0x60 ));       /* RS[3:2] = 0:0 */
  vvOutput( INVALID_HVDM,
            &pleATIVGAIndx,
            0xa0 );                     /* ATI's key to DAC  */
  vvOutput( INVALID_HVDM,
            &pleATIVGAData,
            pvd->VdmSVGA.aregATIData [0xa0] );
  psCurDacInfo->pfnDacSave( hvdm );                             /*          */
  pvd->VdmSVGA.aregATIData [0xa0] = bDACKey;
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach32DacRestore()
 *
 * DESCRIPTION   = Restore DAC state
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach32DacRestore(                           /*          */
  HVDM hvdm )
{
  BYTE bDACKey;
  register PVDMDATA pvd = pVDMData(hvdm);

  /* Add save and restore RS[3:2] if necessary */
  bDACKey = pvd->VdmSVGA.aregATIData [0xa0];
  pvd->VdmSVGA.aregATIData [0xa0] &=
    ~ (0x03 << ZEROBITS( 0x60 ));       /* RS[3:2] = 0:0 */
  vvOutput( INVALID_HVDM,
            &pleATIVGAIndx,
            0xa0 );                     /* ATI's key to DAC  */
  vvOutput( INVALID_HVDM,
            &pleATIVGAData,
            pvd->VdmSVGA.aregATIData [0xa0] );
  psCurDacInfo->pfnDacRestore( hvdm );                          /*          */
  pvd->VdmSVGA.aregATIData [0xa0] = bDACKey;
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach64DacRS2Clear()
 *
 * DESCRIPTION   = Reset DAC RS2
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach64DacRS2Clear(                          /*          */
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  pvd->VdmSVGA.wRegShadow [0x30] &= ~ (0x01 << ZEROBITS( 0x01 ) );
  vvOutputWord( INVALID_HVDM,
                &sATIMach64TrapRegInfo [0x30], /* 0x62ec */
                pvd->VdmSVGA.wRegShadow [0x30] );
  vvATIMach32DacRS2Clear( hvdm );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach64DacRS2Set()
 *
 * DESCRIPTION   = Reset DAC RS2
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach64DacRS2Set(                            /*          */
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  pvd->VdmSVGA.wRegShadow [0x30] |= (0x01 << ZEROBITS( 0x01 ) );
  vvOutputWord( INVALID_HVDM,
                &sATIMach64TrapRegInfo [0x30], /* 0x62ec */
                pvd->VdmSVGA.wRegShadow [0x30] );
  vvATIMach32DacRS2Set( hvdm );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach64DacRS3()
 *
 * DESCRIPTION   = Set DAC RS3 State
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach64DacRS3(                               /*          */
  HVDM hvdm,
  BOOL bRS3 )
{
  register PVDMDATA pvd = pVDMData(hvdm);

  pvd->VdmSVGA.wRegShadow [0x30] &= ~ 0x02;
  pvd->VdmSVGA.wRegShadow [0x30] |= (bRS3 << ZEROBITS( 0x02 ) );
  vvOutputWord( INVALID_HVDM,
                &sATIMach64TrapRegInfo [0x30], /* 0x62ec */
                pvd->VdmSVGA.wRegShadow [0x30] );
  vvATIMach32DacRS3( hvdm, bRS3 );
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach64DacSave()
 *
 * DESCRIPTION   = Save DAC state
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach64DacSave(                              /*          */
  HVDM hvdm )
{
  WORD wDACKey;
  register PVDMDATA pvd = pVDMData(hvdm);

  /* Add save and restore RS[3:2] */
  wDACKey = pvd->VdmSVGA.wRegShadow [0x30]; /* 0x62ec */
  pvd->VdmSVGA.wRegShadow [0x30] &=
    ~ (0x03 << ZEROBITS( 0x03 ));       /* RS[3:2] = 0:0 */
  vvOutputWord( INVALID_HVDM,
                &sATIMach64TrapRegInfo [0x30], /* 0x62ec */
                pvd->VdmSVGA.wRegShadow [0x30] );
  vvATIMach32DacSave( hvdm );
  pvd->VdmSVGA.wRegShadow [0xa0] = wDACKey;
}
                                                                /*          */
/***************************************************************************
 *
 * FUNCTION NAME = vvATIMach64DacRestore()
 *
 * DESCRIPTION   = Restore DAC state
 *
 * INPUT         = NONE
 *
 * OUTPUT        = NONE
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATIMach64DacRestore(                           /*          */
  HVDM hvdm )
{
  BYTE wDACKey;
  register PVDMDATA pvd = pVDMData(hvdm);

  /* Add save and restore RS[3:2] if necessary */
  wDACKey = pvd->VdmSVGA.wRegShadow [0x30]; /* 0x62ec */
  pvd->VdmSVGA.wRegShadow [0x30] &=
    ~ (0x03 << ZEROBITS( 0x03 ));       /* RS[3:2] = 0:0 */
  vvOutputWord( INVALID_HVDM,
                &sATIMach64TrapRegInfo [0x30], /* 0x62ec */
                pvd->VdmSVGA.wRegShadow [0x30] );
  vvATIMach32DacRestore( hvdm );
  pvd->VdmSVGA.wRegShadow [0xa0] = wDACKey;
}

/***************************************************************************
 *
 * FUNCTION NAME = vvATISetBank()
 *
 * DESCRIPTION   = Set ATI bank register
 *
 *                 Set single bank mode for access to video RAM.  Bank
 *                 selection assumes single-bank mode and bank size 64k.
 *
 *                 ATI extended registers are on port 0x1CE.
 *
 *                 We should probably restore the state of the Miscellaneous
 *                 and Memory Page select registers, but hopefully that's
 *                 done as part of Save/Restore IO state.
 *
 * INPUT         = hvdm
 *                 ulBank
 *                 fSetWriteBank
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

VOID PRIVENTRY vvATISetBank(
  HVDM hvdm,
  ULONG ulBank,
  BOOL fSetWriteBank )
{
  register BYTE bBank,bTmp;

  fSetWriteBank;                        /* shut the compiler up    */

  bBank = (BYTE)(ulBank << 1);          /* shift into place */  /*          */
  if( ulSVGAChipType >= ATI_88800_CHIP )                        /*          */
  {                                                             /*          */
    vvOutputWord( hvdm,                                         /*          */
                  &psCurAcceleratorInfo->                       /*          */
                    psAcceleratorTrapRegInfo                    /*          */
                      [psCurAcceleratorInfo->                   /*          */
                        puifnAcceleratorPortIndex( 0x56ec )],   /*          */
                  bBank );                                      /*          */
    vvOutputWord( hvdm,                                         /*          */
                  &psCurAcceleratorInfo->                       /*          */
                    psAcceleratorTrapRegInfo                    /*          */
                      [psCurAcceleratorInfo->                   /*          */
                        puifnAcceleratorPortIndex( 0x5aec )],   /*          */
                  bBank );                                      /*          */
    bBank++;                                                    /*          */
    vvOutputWord( hvdm,                                         /*          */
                  &psCurAcceleratorInfo->                       /*          */
                    psAcceleratorTrapRegInfo                    /*          */
                      [psCurAcceleratorInfo->                   /*          */
                        puifnAcceleratorPortIndex( 0x56ee )],   /*          */
                  bBank );                                      /*          */
    vvOutputWord( hvdm,                                         /*          */
                  &psCurAcceleratorInfo->                       /*          */
                    psAcceleratorTrapRegInfo                    /*          */
                      [psCurAcceleratorInfo->                   /*          */
                        puifnAcceleratorPortIndex( 0x5aee )],   /*          */
                  bBank );                                      /*          */
  }                                                             /*          */
  /* Do always because 88800 needs this in 16 color modes     *//*          */
  bBank &= ~ 0xe1;                      /* Prevent overrun    *//*          */
  vvOutput( hvdm,                       /* First set up for Single Bank Mode*/
            &pleATIVGAIndx,
            0xbe );                     /* Miscellaneous reg  */
  bTmp = vvInput( hvdm,
                  &pleATIVGAData )      /* get curr contents  */
         & ~0x08;
  vvOutput( hvdm,
            &pleATIVGAIndx,
            0xbe );                     /* clear dual pg mode */
  vvOutput( hvdm,
            &pleATIVGAData,
            bTmp );                     /* restore sngl pg md */
  vvOutput( hvdm,
            &pleATIVGAIndx,
            0xb2 );                     /* Memory Page Select */
  bTmp = (vvInput( hvdm,
                  &pleATIVGAData )      /* get curr contents  */
          & 0xe1)                       /* isolate bank sel   */
         | bBank;                       /* add in bank sel    *//*          */
  vvOutput( hvdm,
            &pleATIVGAIndx,
            0xb2 );                     /* Memory Page Select */
  vvOutput( hvdm,
            &pleATIVGAData,
            bTmp );                     /* Finally set bank   *//*          */
}

/***************************************************************************
 *
 * FUNCTION NAME = vvATIGetBank()
 *
 * DESCRIPTION   = Get ATI bank register
 *
 *                 The ATI Bank Register can be used in one of two modes.
 *
 *                     In Dual Bank Mode: bits 7-5 are read bank
 *                                             3-1 are write bank
 *
 *                     In Single Bank Mode: bits 4-1 are read/write bank
 *
 * INPUT         = hvdm
 *                 fGetWriteBank
 *
 * OUTPUT        = ulBank
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ****************************************************************************/

ULONG PRIVENTRY vvATIGetBank(
  HVDM hvdm,
  BOOL fGetWriteBank )
{
  BYTE bBank,bTmp;
  register BYTE bATIIndex;

  if( ulSVGAChipType >= ATI_88800_CHIP )                        /*          */
  {                                                             /*          */
    bBank = (BYTE)                                              /*          */
      vvInputWord( hvdm,                                        /*          */
                   &psCurAcceleratorInfo->                      /*          */
                     psAcceleratorTrapRegInfo                   /*          */
                       [psCurAcceleratorInfo->                  /*          */
                         puifnAcceleratorPortIndex              /*          */
                           ( fGetWriteBank                      /*          */
                             ? 0x56ec                           /*          */
                             : 0x5aec )] );                     /*          */
    bBank >>= 1;                                                /*          */
  }                                                             /*          */
  else                                                          /*          */
  {                                                             /*          */
    bATIIndex = vvInput( hvdm,                                  /*          */
                         &pleATIVGAIndx )
                | 0x80;                                         /*          */
    vvOutput( hvdm,
              &pleATIVGAIndx,                                   /*          */
              0xbe );                   /* Miscellaneous reg  */
    bTmp = vvInput( hvdm,
                    &pleATIVGAData );   /* get current        *//*          */
    vvOutput( hvdm,
              &pleATIVGAIndx,                                   /*          */
              0xb2 );                   /* Memory Page Select */
    bBank = vvInput( hvdm,
                     &pleATIVGAData );  /* get contents       *//*          */
    vvOutput( hvdm,
              &pleATIVGAIndx,
              bATIIndex );                                      /*          */
    bBank >>= ((fGetWriteBank | ~(bTmp & 0x08))
               ? 1                      /* bit set => dual page mode */
               : 5 );                   /* otherwise single bank mode */
    bBank &= 0x0f;                                              /*          */
  }                                                             /*          */
  return( bBank );                                              /*          */
}

/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach32PortIndex()
 *
 * DESCRIPTION   = Get index for write of an accelerator data register
 *
 * INPUT         = port
 *
 * OUTPUT        = table index for port
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ***********************************************************************/

UINT    PRIVENTRY vvATIMach32PortIndex( PORT port )
{
  return( ((port & 0xfc00) >> 9) | ((port & 0x0002) >> 1) );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach32Chip()
 *
 * DESCRIPTION   = Has some type of accelerator chip
 *                 (means Chip exists, does not mean Chip active)
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVCreate (to decide whether to create semaphores)
 *      vvAcceleratorIsOn
 *      vvAcceleratorSetBgndOnlyHooks
 *      vvAcceleratorSetIOHooks
 *      vvAcceleratorInstallIOHooks
 *      vvAcceleratorUpdateIOState
 *      vvAcceleratorRestoreIOState
 *
 ***********************************************************************/
BOOL PRIVENTRY vvATIMach32Chip( VOID )
{
  return( ulSVGAChipType >= ATI_38800_CHIP );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach32IsOn()
 *
 * DESCRIPTION   = Is in accelerator mode
 *
 *                 This routine CAN assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorIsOn
 *
 ***********************************************************************/
BOOL    PRIVENTRY vvATIMach32IsOn(
  HVDM hvdm )
{
  return( vvA8514IsOn( hvdm )
          || (*pVDM( hvdm,
                     PWORD,
                     psCurAcceleratorInfo->psAcceleratorTrapRegInfo
                       [psCurAcceleratorInfo->
                         puifnAcceleratorPortIndex( 0x4aee )]
                           .pvTrapWriteShadow )
              & 0x01) );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach32Init()
 *
 * DESCRIPTION   = Initialize addressing of accelerator registers.
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorCreate
 *
 ***********************************************************************/

VOID    PRIVENTRY vvATIMach32Init(
  HVDM hvdm )
{
  if( ulSVGAChipType <= ATI_38800_CHIP )
  {
    /*
    ** Some registers are write only.
    ** So we want to avoid reading them during UpdateIoState.
    ** This would mess up those values we so carefully trapped!
    ** We can allow writes to non-existent registers.
    ** As long as these predecessor chips have unique address decoding!
    */
    vvA8514WriteOnly( 0x1aee );
    vvA8514WriteOnly( 0x36ee );
    vvA8514WriteOnly( 0x3aee );
    vvA8514WriteOnly( 0x62ee );
    vvA8514WriteOnly( 0x8eee );
    vvA8514WriteOnly( 0x92ee );
    vvA8514WriteOnly( 0xb2ee );
    vvA8514WriteOnly( 0xb6ee );
    vvA8514WriteOnly( 0xbaee );
    vvA8514WriteOnly( 0xc6ee );
    vvA8514WriteOnly( 0xcaee );
    vvA8514WriteOnly( 0xceee );
    vvA8514WriteOnly( 0xdaee );
    vvA8514WriteOnly( 0xdeee );
    vvA8514ReadOnly( 0x4aee );
  }
  vvA8514Init( hvdm );                                          /*          */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvMach64WriteWRegByteL()
 *
 * DESCRIPTION   = Write low byte of accelerator word register
 *
 *                 This registered subroutine is called whenever a VDM
 *                 writes a byte to the lower half of an accelerator word
 *                 register (ie, one of those listed in aportS3WReg).
 *
 * INPUT         = bLow == output data
 *                 port == port address to write
 *                 pcrf -> VDM register frame
 *
 * OUTPUT        = Returns data from port
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ***********************************************************************/

VOID    HOOKENTRY vvMach64WriteWRegByteL(
  BYTE bData,
  ULONG port,
  PCRF pcrf )
{
  register BOOL bIsCmd;

  /*
  ** Allow all kinds of background access except commands!
  */
  bIsCmd = (((port & ~0x0001) == 0x66ec)
            && (bData & 0x10));
              /* Enable EEPROM read/write for ATI Mach64 */
                                        /* These bits change other regs! */
  vvAcceleratorWrite( &psCurAcceleratorInfo->
                        psAcceleratorTrapRegInfo
                          [psCurAcceleratorInfo->
                            puifnAcceleratorPortIndex( port )],
                      &sTrapWRegLow,
                      (PVOID) SSToDS( &bData ),
                      bIsCmd );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvMach64WriteWRegByteH()
 *
 * DESCRIPTION   = Write high byte of accelerator word register
 *
 *                 This registered subroutine is called whenever a VDM
 *                 writes a byte to the upper half of an accelerator word
 *                 register (ie, one of those listed in aportS3WReg).
 *
 * INPUT         = bHigh == output data
 *                 port  == port address to write
 *                 pcrf  -> VDM register frame
 *
 * OUTPUT        = Returns data from port
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ***********************************************************************/

VOID    HOOKENTRY vvMach64WriteWRegByteH(
  BYTE bData,
  ULONG port,
  PCRF pcrf )
{
  register BOOL bIsCmd;
  register PSTRAPREGINFO psTrapRegInfo;

  psTrapRegInfo =
    &psCurAcceleratorInfo->
      psAcceleratorTrapRegInfo
        [psCurAcceleratorInfo->
          puifnAcceleratorPortIndex( port )];
  /*
  ** Allow all kinds of background access except commands!
  */
  bIsCmd = FALSE;
                                        /* These bits change other regs! */
  vvAcceleratorWrite( psTrapRegInfo,
                      &sTrapWRegHigh,
                      (PVOID) SSToDS( &bData ),
                      bIsCmd );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvMach64WriteWRegWord()
 *
 * DESCRIPTION   = Write accelerator word register
 *
 *                 This registered subroutine is called whenever a VDM
 *                 writes to an accelerator word register (ie, one of those
 *                 listed in aportS3WReg).
 *
 * INPUT         = wData == output data
 *                 port  == port address to write
 *                 pcrf  -> VDM register frame
 *
 * OUTPUT        = Returns data from port
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ***********************************************************************/

VOID    HOOKENTRY vvMach64WriteWRegWord(
  WORD wData,
  ULONG port,
  PCRF pcrf )
{
  register BOOL bIsCmd;
  register PSTRAPREGINFO psTrapRegInfo;

  psTrapRegInfo =
    &psCurAcceleratorInfo->
      psAcceleratorTrapRegInfo
        [psCurAcceleratorInfo->
          puifnAcceleratorPortIndex( port )];
  /*
  ** Allow all kinds of background access except commands!
  */
  bIsCmd = (((port & ~0x0001) == 0x66ec)
            && (wData & 0x0010));
              /* Enable EEPROM read/write for ATI Mach64 */
                                        /* These bits change other regs! */
  vvAcceleratorWrite( psTrapRegInfo,
                      &sTrapWRegWhole,
                      (PVOID) SSToDS( &wData ),
                      bIsCmd );
}

#pragma  END_SWAP_CODE                                          /*          */
                                                                /*          */
#pragma  BEGIN_SWAP_DATA                                        /*          */
                                                                /*          */
IOH iohMach64wreg [2] =                                         /*          */
{                                                               /*          */
  {                                                             /*          */
    vvA8514ReadWRegByteL, vvMach64WriteWRegByteL,               /*          */
    vvA8514ReadWRegWord,  vvMach64WriteWRegWord,                /*          */
    NULL,                                                       /*          */
  },                                                            /*          */
  {                                                             /*          */
    vvA8514ReadWRegByteH, vvMach64WriteWRegByteH,               /*          */
    NULL,                 NULL,                                 /*          */
    NULL,                                                       /*          */
  },                                                            /*          */
};                                                              /*          */
                                                                /*          */
#pragma  END_SWAP_DATA                                          /*          */
                                                                /*          */
#pragma  BEGIN_SWAP_CODE                                        /*          */
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach64PortIndex()
 *
 * DESCRIPTION   = Get index for write of an accelerator data register
 *
 * INPUT         = port
 *
 * OUTPUT        = table index for port
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 ***********************************************************************/

UINT    PRIVENTRY vvATIMach64PortIndex(                         /*          */
  PORT port )
{
  return( ((port & 0x7c00) >> 9) | ((port & 0x0002) >> 1) );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach64Chip()
 *
 * DESCRIPTION   = Has some type of accelerator chip
 *                 (means Chip exists, does not mean Chip active)
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      VVCreate (to decide whether to create semaphores)
 *      vvAcceleratorIsOn
 *      vvAcceleratorSetBgndOnlyHooks
 *      vvAcceleratorSetIOHooks
 *      vvAcceleratorInstallIOHooks
 *      vvAcceleratorUpdateIOState
 *      vvAcceleratorRestoreIOState
 *
 ***********************************************************************/

BOOL PRIVENTRY vvATIMach64Chip( VOID )                          /*          */
{
  return( ulSVGAChipType >= ATI_68800_CHIP );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach64IsOn()
 *
 * DESCRIPTION   = Is in accelerator mode
 *
 *                 This routine CAN assume
 *                 that there IS an accelerator chip
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorIsOn
 *
 ***********************************************************************/

BOOL    PRIVENTRY vvATIMach64IsOn(                              /*          */
  HVDM hvdm )
{
  /*!! Can't tell without memory mapped register code! */
  return( TRUE );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach64Busy()
 *
 * DESCRIPTION   = Test for accelerator busy
 *
 * INPUT         = hvdm
 *
 * OUTPUT        = TRUE if busy, FALSE if not
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorRead
 *      vvAcceleratorWaitOnEngine
 *
 ***********************************************************************/

BOOL    PRIVENTRY vvATIMach64Busy(                              /*          */
  HVDM hvdm )
{
  /*!! Can't tell without memory mapped register code! */
  return( FALSE );
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach64Reset()
 *
 * DESCRIPTION   = Force the accelerator to be UNbusy, if possible.
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = TRUE if busy, FALSE if not
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorWaitOnEngine
 *
 ***********************************************************************/

VOID    PRIVENTRY vvATIMach64Reset(                             /*          */
  HVDM hvdm )
{
  /*!! Can't do this without memory mapped register code! */
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIUpdateScrnState()
 *
 * DESCRIPTION   = Return line len in bytes for accelerated modes, depending on
 *                 the memory map organization.
 *
 * INPUT         = None
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL = TRUE/FALSE
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvAcceleratorUpdateScrnState
 *
 ***********************************************************************/

VOID    PRIVENTRY vvATIUpdateScrnState(                   /*                       */
  HVDM hvdm )
{
}
                                                                /*          */
/***********************************************************************
 *
 * FUNCTION NAME = vvATIMach64RestoreIoState()
 *
 * DESCRIPTION   = Transfer virtual I/O state to hardware
 *
 *
 * INPUT         = hvdm -> VDM
 *
 * OUTPUT        = None
 *
 * RETURN-NORMAL =
 * RETURN-ERROR  =
 *
 * CALLED BY
 *      vvS3RestoreIoState
 *      vvAcceleratorRestoreIoState
 *
 ***********************************************************************/

VOID    PRIVENTRY vvATIMach64RestoreIoState(                    /*          */
  HVDM hvdm )
{
  register PVDMDATA pvd = pVDMData( hvdm );
  WORD wData;
  PORT port;
  UINT uiIndex;
  PSTRAPREGINFO psCurTrapRegInfo;

  for (uiIndex = 0;
       uiIndex < psCurAcceleratorInfo->uiAcceleratorTrapWRegSize;
       uiIndex++)
  {
    psCurTrapRegInfo =
      &psCurAcceleratorInfo->
        psAcceleratorTrapRegInfo [uiIndex];
    if( (psCurTrapRegInfo->fTrapType & WRITE_ALL)
        == WRITE_MANY )
    {
      wData =
        *pVDM( hvdm,
               PWORD,
               psCurTrapRegInfo->pvTrapWriteShadow );
      port = psCurTrapRegInfo->portTrap;
      _asm
      {
        mov  dx, word ptr port
        mov  ax, wData
        out  dx, ax
      }
    }
  }
}

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

VOID PRIVENTRY vvATIEditTables( VOID )
{
  /* fSVGASeqFixups = TRUE; */ /* Default! */            /*          */
  rleATIMemATI30.rle_flags &= ~PORTF_NOTVALIDSVGAPORT;   /* V2.2SEN01 */
  pleATIVGAData.sTrapBRegInfo.fTrapType &= ~PORTF_NOTVALIDSVGAPORT;    /*            */
  pleATIVGAIndx.sTrapBRegInfo.fTrapType &= ~PORTF_NOTVALIDSVGAPORT;    /*            */
  /*
  ** vvPMIPortToPPLE enables all appropriate trap list entries
  ** by removing NOTRAP flag when port found in trapreg list!
  */
  if( (ulSVGAChipType == ATI_38800_CHIP)                        /*          */
       || (ulSVGAChipType == ATI_68800_CHIP)                    /*          */
       || (ulSVGAChipType == ATI_88800_CHIP) )                  /*          */
  {                                                             /*          */
    /* Extended DAC's are in a different place than usual */    /*          */
    ppleDacExtMask = &pleATIDacMask;                            /*          */
    ppleDacExtRead = &pleATIDacRead;                            /*          */
    ppleDacExtWrite = &pleATIDacWrite;                          /*          */
    ppleDacExtData = &pleATIDacData;                            /*          */
    /*
    ** Set the fall back MMIO region.                                     
    */
    pvdmStartupMMIOActive = (PVDM) 0xBf000;
    npgStartupMMIOActive = 1;
  }                                                             /*          */
  if( ulSVGAChipType >= ATI_88800_CHIP )                        /*          */
  {                                                             /*          */
    pleATIDacWrite.sTrapBRegInfo.portTrap = 0x5eec+0x00;        /*          */
    pleATIDacData.sTrapBRegInfo.portTrap = 0x5eec+0x01;         /*          */
    pleATIDacMask.sTrapBRegInfo.portTrap = 0x5eec+0x02;         /*          */
    pleATIDacRead.sTrapBRegInfo.portTrap = 0x5eec+0x03;         /*          */
    sATIAdapterInfo.psAcceleratorInfo = &sATIMach64Info;        /*          */
    sATIAdapterInfo.pfnSVGADacRS2Clear =                        /*          */
      &vvATIMach64DacRS2Clear;                                  /*          */
    sATIAdapterInfo.pfnSVGADacRS2Set =                          /*          */
      &vvATIMach64DacRS2Set;                                    /*          */
    sATIAdapterInfo.pfnSVGADacRS3 =                             /*          */
      &vvATIMach64DacRS3;                                       /*          */
    sATIAdapterInfo.sVGAInfo.pfnVGADACSave =                    /*          */
      &vvATIMach64DacSave;                                      /*          */
    sATIAdapterInfo.sVGAInfo.pfnVGADACRestore =                 /*          */
      &vvATIMach64DacRestore;                                   /*          */
  }                                                             /*          */
}

#pragma  END_SWAP_CODE

#pragma  BEGIN_SWAP_DATA

SA8514INFO sATIMach32Info =
{
  {
    sATIMach32TrapRegInfo,
    ATIMACH32TRAPREGSIZE,
    &vvATIMach32PortIndex,
    &vvATIMach32Chip,
    &vvATIMach32IsOn,
    &vvA8514Create,                     //V2.2SEN01
    NULL,                               //V2.2SEN01
    &vvA8514Busy,
    &vvA8514Reset,
    &vvA8514InstallIoHooks,
    &vvA8514SetIoHooks,
    &vvA8514SetBgndOnlyHooks,
//              &vvA8514UpdateScrnState,
    &vvATIUpdateScrnState,                                      /*          */
    &vvA8514UpdateIoState,
    &vvA8514RestoreIoState,
    &vvATIMach32Init,
  },
  &vvA8514ReadMFRegShadow,
};

SACCELERATORINFO sATIMach64Info =                               /*          */
{
  sATIMach64TrapRegInfo,
  ATIMACH64TRAPREGSIZE,
  &vvATIMach64PortIndex,
  &vvATIMach64Chip,
  &vvATIMach64IsOn,
  &vvA8514Create,                                               /*V2.2SEN01 */
  NULL,
  &vvATIMach64Busy,
  &vvATIMach64Reset,
  &vvA8514InstallIoHooks,
  &vvA8514SetIoHooks,
  &vvA8514SetBgndOnlyHooks,
//            &vvATIMach64UpdateScrnState,
  &vvATIUpdateScrnState,                                      /*          */
  &vvA8514UpdateIoState,
  &vvATIMach64RestoreIoState,
  &vvA8514Init,
};

SSVGAINFO sATIAdapterInfo =                                     /*          */
{
  { /* SVGAINFO */                                              /*          */
    { /* SEGAINFO */
      { /* SCGAINFO */
        &vvEGAAdjustedPort,
        &vvATIStartAddr,
        &vvEGAOddEvenMode,
        &vvEGAHighResMode,
        &vvEGAHorzDspEnd,
        &vvEGAHorzLogEnd,                                       /*           */
        &vvVGAVertDspEnd,
        &vvVGABitsPerPixel,
        &vvVGAPrepareSetMode,                                   /*          */
      },
      &vvATIPackedMode,
      &vvVGAVertLineCmp,
    },
    &vvATIMach32DacSave,                                        /*          */
    &vvATIMach32DacRestore,                                     /*          */
  },                                                            /*          */
  &vvATIEditTables,
  &vvATIInterlaced,
  &vvVGAUpdateIoState,
  &vvVGARestoreIoState,
  &vvATISetBank,
  &vvATIGetBank,
  &vvVGAFixSetMode,
  &vvVGAFixSetBgnd,
  &vvVGAWriteGDCDataFgnd,
  &vvVGAReadSEQDataBgnd,
  &vvVGAWriteSEQDataBgnd,
  &vvATIMach32DacRS2Clear,                                      /*          */
  &vvATIMach32DacRS2Set,                                        /*          */
  &vvATIMach32DacRS3,                                           /*          */
  &(sATIMach32Info.sAcceleratorInfo),
  pszATIAdapterName,
  MAX_ATI_CHIP,
  ppszATIChipNames,
  NULL,                                                         /*V2.2SEN01*/
  /*
  ** ATI cleanup fails background mode 3 set, if cleaup issued on top of INIT
  ** data. If issued on top of current desktop values, it works. So, keep the
  ** INT10INITUPDATEENABLED until the cleanup is fixed.
  */
  SVGA_INT10INITUPDATEENABLED,                                  /*          */
};

#pragma  END_SWAP_DATA

