/* $XFree86: xc/programs/Xserver/hw/xfree86/accel/agx/agx.c,v 3.53.2.4 1998/02/07 10:05:04 hohndel Exp $ */
/*
 * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
 * Copyright 1993 by Kevin E. Martin, Chapel Hill, North Carolina.
 * Copyright 1994 by Henry A. Worth, Sunnyvale, California.
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation, and that the name of Thomas Roell not be used in
 * advertising or publicity pertaining to distribution of the software without
 * specific, written prior permission.  Thomas Roell makes no representations
 * about the suitability of this software for any purpose.  It is provided
 * "as is" without express or implied warranty.
 *
 * THOMAS ROELL, KEVIN E. MARTIN, RICKARD E. FAITH, AND HENRY A. WORTH
 * DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 
 * THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA 
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Thomas Roell, roell@informatik.tu-muenchen.de
 *
 * Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu)
 * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu)
 * Rewritten for the Mach32 by Kevin E. Martin (martin@cs.unc.edu)
 * Rewritten for the AGX by Henry A. Worth (haw30@eng.amdahl.com)
 *
 */
/* $XConsortium: agx.c /main/20 1996/10/27 11:04:14 kaleb $ */


#include "X.h"
#include "Xmd.h"
#include "input.h"
#include "scrnintstr.h"
#include "pixmapstr.h"
#include "mipointer.h"
#include "cursorstr.h"

#include "compiler.h"

#include "xf86.h"
#include "xf86Priv.h"
#include "xf86Procs.h"
#include "xf86_OSlib.h"
#include "xf86_HWlib.h"
#include "cfb.h"
#include "cfb16.h"
#ifdef AGX_32BPP
#include "cfb32.h"
#endif
#include "mi.h"
#include "agx.h"
#include "regagx.h"
#include "xf86RamDac.h"
#include "hercRamDac.h"

#define XCONFIG_FLAGS_ONLY
#include "xf86_Config.h"

#ifdef XFreeXDGA
#include "X.h"
#include "Xproto.h"
#include "scrnintstr.h"
#include "servermd.h"
#define _XF86DGA_SERVER_
#include "extensions/xf86dgastr.h"
#endif

extern Bool xf86Resetting, xf86Exiting, xf86ProbeFailed;
extern Bool miDCInitialize();
extern void SetTimeSinceLastInputEvent();

static int agxValidMode(
#if NeedFunctionPrototypes
    DisplayModePtr,
    Bool,
    int
#endif
); 

ScrnInfoRec agxInfoRec = {
    FALSE,		/* Bool configured */
    -1,			/* int tmpIndex */
    -1,			/* int scrnIndex */
    agxProbe,      	/* Bool (* Probe)() */
    agxInit,	        /* Bool (* Init)() */
    agxValidMode,       /* int (* ValidMode)() */
    agxEnterLeaveVT,    /* void (* EnterLeaveVT)() */
    (void(*)())NoopDDA,	/* void (* EnterLeaveMonitor)() */
    (void(*)())NoopDDA,	/* void (* EnterLeaveCursor)() */
    agxAdjustFrame, 	/* void (* AdjustFrame)() */
    agxSwitchMode,      /* Bool (* SwitchMode)() */
    (void (*)())NoopDDA,/* void (* DPMSSet)() */
    agxPrintIdent,	/* void (* PrintIdent)() */
    8,			/* int depth */
    {0, 0, 0},          /* xrgb weight */
    8,			/* int bitsPerPixel */
    PseudoColor,       	/* int defaultVisual */
    -1, -1,		/* int virtualX,virtualY */
    -1,                 /* int displayWidth */
    -1, -1, -1, -1,	/* int frameX0, frameY0, frameX1, frameY1 */
    {0, },	       	/* OFlagSet options */
    {0, },	       	/* OFlagSet clockOptions */
    {0, },	       	/* OFlagSet xconfigFlag */
    NULL,       	/* char *chipset */
    NULL,       	/* char *ramdac */
    {0, 0, 0, 0},	/* int dacSpeeds[MAXDACSPEEDS] */
    0,			/* int dacSpeedBpp */
    0,			/* int clocks */
    {0, },		/* int clock[MAXCLOCKS] */
    0,			/* int maxClock */
    2048,		/* int videoRam */
    0xC0000,            /* int BIOSbase */   
    0,	        	/* unsigned long MemBase */
    240, 180,		/* int width, height */
    0,                  /* unsigned long  speedup */
    NULL,	       	/* DisplayModePtr modes */
    NULL,	       	/* MonPtr monitor */
    NULL,               /* char *clockprog */
    -1,                 /* int textclock */   
    FALSE,              /* Bool bankedMono */
    "AGX",              /* char *name */
    {0, },		/* xrgb blackColour */
    {0, },		/* xrgb whiteColour */
    agxValidTokens,	/* int *validTokens */
    AGX_PATCHLEVEL,	/* char *patchlevel */
    0,		 	/* unsigned int IObase */
    0, 			/* unsigned int PALbase */
    0,			/* unsigned long COPbase */
    POS_DEF_IO_BASE,    /* unsigned int POSbase      */
    -1,                 /* int instance     */
    0,                  /* int s3Madjust    */
    0,                  /* int s3Nadjust    */
    0,                  /* int s3MClk    */
    0,                  /* int chipID    */
    0,                  /* int chipRev   */
    0xA0000,		/* unsigned long VGAbase */
    0,                  /* int s3RefClk    */
    -1,                 /* int s3BlankDelay    */
    0,			/* int textClockFreq */
  NULL,                 /* char* DCConfig */
  NULL,                 /* char* DCOptions */
    0,			/* int MemClk */
    0			/* int LCDClk */
#ifdef XFreeXDGA
    ,0,                  /* int directMode    */
    agxSetVidPage,      /* Set Vid Page    */
    0,                  /* unsigned long physBase    */
    0                  /* int physSize    */
#endif
};

int vgaInterlaceType = VGA_NO_DIVIDE_VERT;
/* void (*vgaSaveScreenFunc)() = (void (*)())NoopDDA; */
void (*vgaSaveScreenFunc)() = vgaHWSaveScreen; 
pointer vgaNewVideoState = NULL;

static Bool LUTissaved = FALSE;
ScreenPtr savepScreen = NULL;
static PixmapPtr ppix = NULL;

static unsigned agxDAIOPorts[ DA_NUM_IO_REG ] = {0, };
static unsigned agxPOSIOPorts[ POS_NUM_IO_REG ] = {0, };

static SymTabRec agxDacTable[] = {
   { NORMAL_DAC,        "normal" },
   { BT481_DAC,         "bt481" },
   { BT482_DAC,         "bt482" },
#if 0  /* not yet directly supported */
   { BT485_DAC,         "bt485" },
   { ATT20C505_DAC,     "att20c505" },
#endif
   { SC15025_DAC,       "sc15025" },
   { HERC_DUAL_DAC,     "herc_dual_dac" },
   { HERC_SMALL_DAC,    "herc_small_dac" },
   { XGA_DAC,           "xga" },
   { ATT490_DAC,        "att20c490" },
   { -1,                "" },
};


unsigned short agxMemorySize = 0;
pointer  agxPhysVidMem = NULL;
pointer  vgaPhysBase = NULL;
pointer  vgaBase = NULL;
pointer  vgaVirtBase = NULL;
pointer  agxVideoMem = NULL;
unsigned long agxVideoBase = 0x0;
unsigned long agxPOSMemBase = 0x0;
unsigned long vgaBankSize = 0x10000;
unsigned long agxBankSize = 0x10000;
unsigned long agxMemBase; 
unsigned long agxFontCacheOffset;
unsigned long agxFontCacheSize;
unsigned long agxFontRowLength;
unsigned int  agxFontRowNumLines;

unsigned long agxScratchOffset;
unsigned long agxScratchSize;
unsigned long agxHWCursorOffset;
Bool     agxHWCursor = FALSE;


extern Bool xf86VTSema;
int agxMaxX, agxMaxY;
int agxVirtX, agxVirtY;
int agxAdjustedVirtX;
int agxDisplayWidth;
Bool  agx128WidthAdjust;
Bool  agx256WidthAdjust;
Bool  agx288WidthAdjust;
Bool agxUse4MbAperture;
Bool (*agxClockSelectFunc)();


Bool agxSaveVGA = TRUE;
Bool agxInited;

pointer      agxGEBase;
pointer      agxGEPhysBase;
unsigned int agxIdxReg;
unsigned int agxDAReg;
unsigned int agxApIdxReg;
unsigned int agxByteData;
unsigned int agxChipId;
unsigned int xf86RamDacBase;

int agxBpp;
int agxWeight = RGB8_PSEUDO; 
extern char *xf86VisualNames[];

agxCRTCRegRec agxCRTCRegs;

extern miPointerScreenFuncRec xf86PointerScreenFuncs;

LUTENTRY agxsavedLUT[256];

typedef struct XGAInfoBlock {
   unsigned char  instance;
   unsigned char  pos0;
   unsigned char  pos1;
   unsigned char  pos2;
   unsigned char  pos3;
   unsigned char  pos4;
   unsigned char  pos5;
   unsigned long  xgaBiosAddress; 
   unsigned long  xgaCoProcAddress;
   unsigned long  xgaIOAddress;
   unsigned long  xgaMemBase;
} XGAInformationBlock;  

static 
GetXGAInfoBlock(instance,info)
   int instance;
   XGAInformationBlock *info;
{
   int i, tmp;
   int  inst = instance;
   int posBase = agxInfoRec.POSbase;

   if (xf86Verbose) {
      ErrorF( "%s %s: ------------- XGA POS Register Probe -------------\n", 
              XCONFIG_PROBED, agxInfoRec.name );
  
      ErrorF( "%s %s: POS Probe Register Base Address: 0x0%x (POSBASE)\n", 
              OFLG_ISSET(XCONFIG_POSBASE, &agxInfoRec.xconfigFlag) 
                 ? XCONFIG_GIVEN : XCONFIG_PROBED,
              agxInfoRec.name, posBase );
   }

   if( posBase & POS_EISA_MASK == POS_EISA_MASK ) {
      ErrorF( "%s %s: EISA POS Probe\n", XCONFIG_PROBED, agxInfoRec.name );

      /* enable pos regs for video board instance */
      outb(posBase+POS_EISA_CONTROL, POS_CONF_EISA_ENABLE_MASK | inst);

      posBase += POS_EISA_OFFSET;
   }
   else {
      ErrorF( "%s %s: ISA POS  Probe\n", XCONFIG_PROBED, agxInfoRec.name );
      if( inst < 0 || inst > 7 ) {
         unsigned char in; 
         inst = -1;
         for( i=0; i<8; i++) {
            GlennsIODelay();
            in = inb(posBase+POS_CONTROL+i);
            if (in != 0xFF) 
               inst = i; 
            if (xf86Verbose) 
               ErrorF( "%s %s: POS instance %d - control register: 0x%x, \
value: 0x%02x\n",
                       XCONFIG_PROBED, agxInfoRec.name,
                       i, POS_CONTROL+i, in );
         }
      }
      else {
         if( inb(posBase+POS_CONTROL+inst) == 0xFF )
            inst = -1;
      }
      if( inst < 0 ) {
         return inst;
      }
      /* enable pos regs for video board instance */
      outb(posBase+POS_CONTROL+inst, POS_CONF_ISA_ENABLE_MASK | inst);
   }

   if( inst < 0 ) {
      return inst;
   }

   GlennsIODelay();
   info->pos0 = inb(posBase);
   GlennsIODelay();
   info->pos1 = inb(posBase+1);
   GlennsIODelay();
   info->pos2 = inb(posBase+2);
   GlennsIODelay();
   info->pos3 = inb(posBase+3);
   GlennsIODelay();
   info->pos4 = inb(posBase+4);
   GlennsIODelay();
   info->pos5 = inb(posBase+5);
   
   /* disable the POS registers */
   GlennsIODelay();
   if( posBase & POS_EISA_MASK == POS_EISA_MASK ) { 
      posBase -= POS_EISA_OFFSET;
      outb(posBase+POS_EISA_CONTROL, 0x0 );
   }
   else {
      outb(posBase+POS_CONTROL+inst, inst & POS_INSTANCE_MASK);
   }

   info->instance = POS_CONF_INSTANCE(info->pos2);

   info->xgaBiosAddress = ((info->pos2 & POS_CONF_EXT_MEM_MASK) 
                             * POS_CONF_EXT_MEM_MULT) + POS_CONF_EXT_MEM_BASE;

   info->xgaCoProcAddress = info->xgaBiosAddress 
                            + POS_CONF_COPROC_REG_OFF
                            + inst * 0x80;

   info->xgaIOAddress =  0x2100 | inst<<4;

   info->xgaMemBase  = (info->pos4 & 0xFE)<<24 | (inst&0x07)<<22 ;

   if (xf86Verbose) {
      ErrorF( "%s %s: POS XGA Instance: %d (INSTANCE)\n", 
              instance < 0 ? XCONFIG_PROBED : XCONFIG_GIVEN,
              agxInfoRec.name, info->instance);

      ErrorF( "%s %s: POS Register 0 - ID hi:   0x%02x\n", XCONFIG_PROBED,
              agxInfoRec.name, info->pos0 );
      ErrorF( "%s %s: POS Register 1 - ID low:  0x%02x\n", XCONFIG_PROBED,
              agxInfoRec.name, info->pos1 );
      ErrorF( "%s %s: POS Register 2 - Ext Mem: 0x%02x\n",
               XCONFIG_PROBED, agxInfoRec.name, info->pos2 );
      ErrorF( "%s %s: POS Register 3 - Bus Arb: 0x%02x\n", XCONFIG_PROBED,
              agxInfoRec.name, info->pos3 );
      ErrorF( "%s %s: POS Register 4 - Dis Adr: 0x%02x\n", XCONFIG_PROBED,
              agxInfoRec.name, info->pos4 );
      ErrorF( "%s %s: POS Register 5 - 1MB Adr: 0x%02x\n", XCONFIG_PROBED,
              agxInfoRec.name, info->pos5 );

      ErrorF( "%s %s: POS XGA External Memory (XGA BIOS) Address: \
0x%06x (BIOSBASE)\n", 
               XCONFIG_PROBED, agxInfoRec.name, info->xgaBiosAddress );

      ErrorF( "%s %s: POS XGA Coproc Mem-Mapped Reg \
Base Address: 0x%06x (COPBASE)\n", 
              XCONFIG_PROBED, agxInfoRec.name, info->xgaCoProcAddress );

      ErrorF( "%s %s: POS XGA I/O Register Base Address: \
0x%04x (IOBASE)\n", 
              XCONFIG_PROBED, agxInfoRec.name, info->xgaIOAddress );

      ErrorF( "%s %s: POS XGA Coproc's Video Memory Base \
Address: 0x%06x (MEMBASE)\n", 
              XCONFIG_PROBED, agxInfoRec.name, info->xgaMemBase );

      ErrorF( "%s %s: ------------- End POS Register Probe -------------\n", 
              XCONFIG_PROBED, agxInfoRec.name );
   }

   return inst;
}
   
/*
 * agxProbe --
 *     Probe the hardware
 */
Bool
agxProbe()
{
   int                   i;
   DisplayModePtr        pMode, pEnd;
   OFlagSet              validOptions;
   int                   tx, ty;
   agxCRTCRegRec         agxProbeCRTC;

   xf86ProbeFailed = FALSE;

   vgaBase = NULL;
   vgaVirtBase = NULL;
   vgaPhysBase = NULL;

   OFLG_ZERO(&validOptions);
   OFLG_SET(OPTION_CLKDIV2, &validOptions);
   OFLG_SET(OPTION_SW_CURSOR, &validOptions);
   OFLG_SET(OPTION_BT485_CURS, &validOptions);
   OFLG_SET(OPTION_BT482_CURS, &validOptions);
   OFLG_SET(OPTION_DAC_8_BIT, &validOptions);
   OFLG_SET(OPTION_DAC_6_BIT, &validOptions);
   OFLG_SET(OPTION_NOACCEL, &validOptions);
   OFLG_SET(OPTION_SYNC_ON_GREEN, &validOptions);
   OFLG_SET(OPTION_8_BIT_BUS, &validOptions);
   OFLG_SET(OPTION_WAIT_STATE, &validOptions);
   OFLG_SET(OPTION_NO_WAIT_STATE, &validOptions);
   OFLG_SET(OPTION_CRTC_DELAY, &validOptions);
   OFLG_SET(OPTION_VRAM_128, &validOptions);
   OFLG_SET(OPTION_VRAM_256, &validOptions);
   OFLG_SET(OPTION_REFRESH_20, &validOptions);
   OFLG_SET(OPTION_REFRESH_25, &validOptions);
   OFLG_SET(OPTION_SPRITE_REFRESH, &validOptions);
   OFLG_SET(OPTION_SCREEN_REFRESH, &validOptions);
   OFLG_SET(OPTION_FIFO_CONSERV, &validOptions);
   OFLG_SET(OPTION_FIFO_MODERATE, &validOptions);
   OFLG_SET(OPTION_FIFO_AGGRESSIVE, &validOptions);
   OFLG_SET(OPTION_VLB_A, &validOptions);
   OFLG_SET(OPTION_VLB_B, &validOptions);
   OFLG_SET(OPTION_FAST_VRAM, &validOptions);
   OFLG_SET(OPTION_SLOW_VRAM, &validOptions);
   OFLG_SET(OPTION_FAST_DRAM, &validOptions);
   OFLG_SET(OPTION_SLOW_DRAM, &validOptions);
   OFLG_SET(OPTION_MED_DRAM, &validOptions);
   OFLG_SET(OPTION_VRAM_DELAY_LATCH, &validOptions);
   OFLG_SET(OPTION_VRAM_DELAY_RAS, &validOptions);
   OFLG_SET(OPTION_VRAM_EXTEND_RAS, &validOptions);
   OFLG_SET(OPTION_ENGINE_DELAY, &validOptions);

   xf86VerifyOptions(&validOptions, &agxInfoRec);

   if( !StrCaseCmp( agxInfoRec.chipset, "XGA-1" ) )
      agxChipId = XGA_1;
   else if( !StrCaseCmp( agxInfoRec.chipset, "XGA-2" ) )
      agxChipId = XGA_2;
   else if( !StrCaseCmp( agxInfoRec.chipset, "AGX-010" ) )
      agxChipId = AGX_10;
   else if( !StrCaseCmp( agxInfoRec.chipset, "AGX-014" ) )
      agxChipId = AGX_14;
   else if( !StrCaseCmp( agxInfoRec.chipset, "AGX-015" ) )
      agxChipId = AGX_15;
   else if( !StrCaseCmp( agxInfoRec.chipset, "AGX-016" ) )
      agxChipId = AGX_16;
   else {
      agxChipId = 0;
      agxInfoRec.chipset = "UNKNOWN";
      ErrorF("%s %s:Valid AGX/XGA Chip type must be specified.\n",
             XCONFIG_GIVEN, agxInfoRec.name);
      return FALSE;
   }
   ErrorF( "%s %s: Graphics chip type \"%s\" (CHIPSET)\n", 
           XCONFIG_GIVEN, agxInfoRec.name, agxInfoRec.chipset );

   xf86ClearIOPortList(agxInfoRec.scrnIndex); 

   /* probe and auto-config XGA chips */ 
   if( XGA_SERIES(agxChipId) && agxInfoRec.POSbase != 0 ) {
      int inst;
      XGAInformationBlock info = { 0xFF, };

      if( agxInfoRec.instance < 0 || agxInfoRec.instance > 7 )
         agxInfoRec.instance = -1;

      for( i= 0; i <= POS_LAST_IO_REG; i++ )
         agxPOSIOPorts[ i ] = agxInfoRec.POSbase + i;

      xf86AddIOPorts(agxInfoRec.scrnIndex, POS_NUM_IO_REG, agxPOSIOPorts);

      xf86EnableIOPorts(agxInfoRec.scrnIndex);

      inst = GetXGAInfoBlock(agxInfoRec.instance,&info);

      xf86DisableIOPorts(agxInfoRec.scrnIndex);
      xf86ClearIOPortList(agxInfoRec.scrnIndex); 

      if( inst < 0 || inst > 7 ) {
         ErrorF( "%s %s: Unable to probe the XGA POS registers, see README.agx \
for information on how to manually configure.\n", 
                 XCONFIG_GIVEN, agxInfoRec.name );
         if( !OFLG_ISSET(XCONFIG_INSTANCE, &agxInfoRec.xconfigFlag) )
            return FALSE;
      }
      else {
         if( !OFLG_ISSET(XCONFIG_INSTANCE, &agxInfoRec.xconfigFlag) ) {
            agxInfoRec.instance = info.instance;
         }
         if( !OFLG_ISSET(XCONFIG_MEMBASE, &agxInfoRec.xconfigFlag) ) {
            agxInfoRec.MemBase  = (info.pos4 & 0xFE)<<24
                                  |  (agxInfoRec.instance&0x07)<<22 ;
         }
         if( !OFLG_ISSET(XCONFIG_COPBASE, &agxInfoRec.xconfigFlag) ) {
            agxInfoRec.COPbase  = info.xgaCoProcAddress;
         }
         if( !OFLG_ISSET(XCONFIG_IOBASE, &agxInfoRec.xconfigFlag) ) {
            agxInfoRec.IObase   = info.xgaIOAddress;
         }
         if( !OFLG_ISSET(XCONFIG_BIOSBASE, &agxInfoRec.xconfigFlag) ) {
            agxInfoRec.BIOSbase   = info.xgaBiosAddress;
         }
      }
   }
   else {  /* AGX */
      if( !OFLG_ISSET(XCONFIG_INSTANCE, &agxInfoRec.xconfigFlag) ) {
         agxInfoRec.instance = 6;
      }
      if( !OFLG_ISSET(XCONFIG_MEMBASE, &agxInfoRec.xconfigFlag) ) {
         agxInfoRec.MemBase  = (agxInfoRec.instance&0x07)<<22 ;
      }
   }

   /* configure I/O address */
   if(agxInfoRec.IObase == 0)
      if(AGX_SERIES(agxChipId))
          agxInfoRec.IObase = DA_AGX_IO_BASE;
      else
          agxInfoRec.IObase = DA_XGA_IO_BASE + (agxInfoRec.instance << 4);

   ErrorF( "%s %s: Instance = %d (INSTANCE).\n",
            OFLG_ISSET(XCONFIG_INSTANCE, &agxInfoRec.xconfigFlag) 
               ? XCONFIG_GIVEN : XCONFIG_PROBED,
            agxInfoRec.name, agxInfoRec.instance, agxInfoRec.IObase );

   ErrorF( "%s %s: I/O Mapped Register Base Address = 0x%04x (IOBASE)\n",
            OFLG_ISSET(XCONFIG_IOBASE, &agxInfoRec.xconfigFlag) 
               ? XCONFIG_GIVEN : XCONFIG_PROBED,
            agxInfoRec.name, agxInfoRec.IObase );

   /* XGA direct access I/O regs */
   for( i= 0; i <= DA_LAST_IO_REG; i++ )
      agxDAIOPorts[ i ] = agxInfoRec.IObase + i;

   xf86AddIOPorts(agxInfoRec.scrnIndex, Num_VGA_IOPorts, VGA_IOPorts);
   xf86AddIOPorts(agxInfoRec.scrnIndex, DA_NUM_IO_REG, agxDAIOPorts);
   xf86EnableIOPorts(agxInfoRec.scrnIndex);


   /* various address globals */
   agxIdxReg   = agxInfoRec.IObase + DA_INDEX_REGISTER;
   agxApIdxReg = agxInfoRec.IObase + DA_APERATURE_INDEX;
   agxDAReg    = agxInfoRec.IObase;
   agxByteData = agxInfoRec.IObase + DA_DATA_BYTE_REG;
   vgaIOBase   = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
   vgaPhysBase    = (pointer)agxInfoRec.VGAbase;
   agxPhysVidMem  = vgaPhysBase;
   xf86RamDacBase = 0x3C0;

   /* determine the video memory aperature base address */
   switch( agxInfoRec.VGAbase ) {
      unsigned char oldmode;

      case 0xA0000:
      case 0xB0000:
         break;
      default:
         oldmode = inb(agxDAReg+DA_OP_MODE) & DA_OM_MASK;
         outb(agxDAReg+DA_OP_MODE,oldmode|DA_OM_DISP_VGA_XGA_EN);

         switch( inb(agxDAReg+DA_APERATURE_CNTL) & DA_AC_MASK ) {
            case DA_AC_64K_AT_B0000:
               agxInfoRec.VGAbase = 0xB0000;
               break;
            case DA_AC_64K_AT_A0000:
            default:
               agxInfoRec.VGAbase = 0xA0000;
               break;

         }
         outb(agxDAReg+DA_OP_MODE,oldmode);
   }
   ErrorF( "%s %s: Video Memory 64K Aperature Base Address = 0x%05x \
(VGABASE)\n",
            OFLG_ISSET(XCONFIG_VGABASE, &agxInfoRec.xconfigFlag) 
               ? XCONFIG_GIVEN : XCONFIG_PROBED,
            agxInfoRec.name, agxInfoRec.VGAbase );

   /* various address globals */
   agxIdxReg   = agxInfoRec.IObase + DA_INDEX_REGISTER;
   agxApIdxReg = agxInfoRec.IObase + DA_APERATURE_INDEX;
   agxDAReg    = agxInfoRec.IObase;
   agxByteData = agxInfoRec.IObase + DA_DATA_BYTE_REG;
   vgaIOBase   = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
   vgaPhysBase    = (pointer)agxInfoRec.VGAbase;
   agxPhysVidMem  = vgaPhysBase;
   xf86RamDacBase = 0x3C0;

   /* map the video memory aperature */
   vgaBase = xf86MapVidMem(agxInfoRec.scrnIndex, VGA_REGION,
                           (pointer)vgaPhysBase, vgaBankSize);
   xf86MapDisplay(agxInfoRec.scrnIndex, VGA_REGION); 
   agxVideoMem = vgaBase;

   if (xf86Verbose) {
      ErrorF("%s %s: Using 64 kb aperture @phys-0x%x, virt-0x%x\n",
             OFLG_ISSET(OPTION_NOLINEAR_MODE, &agxInfoRec.options)
		? XCONFIG_GIVEN : XCONFIG_PROBED,
             agxInfoRec.name, vgaPhysBase, vgaBase );
   }

   /* determine the coprocessor memory mapped register base */
   if(AGX_SERIES(agxChipId)) {
      switch( agxInfoRec.COPbase ) {
         unsigned char oldmode;

         case 0xB1F00:
         case 0xD1F00:
            break;
         default:
            /* enable XGA registers */
            oldmode = inb(agxDAReg+DA_OP_MODE) & DA_OM_MASK;
            outb(agxDAReg+DA_OP_MODE,oldmode|DA_OM_DISP_VGA_XGA_EN);

            outb(agxIdxReg, IR_M3_MODE_REG_3);
            if(inb(agxByteData)&IR_M3_B1F00_GE_ADDRESS)
               if( agxInfoRec.VGAbase != 0xB0000 )
                  agxInfoRec.COPbase = 0xB1F00;
               else
                  agxInfoRec.COPbase = 0xD1F00;
            else
                agxInfoRec.COPbase = 0xD1F00;

            /* disable XGA registers */
            outb(agxDAReg+DA_OP_MODE,oldmode);
      }
   }
   else if( !OFLG_ISSET(XCONFIG_COPBASE, &agxInfoRec.xconfigFlag) ) {
      if( OFLG_ISSET(XCONFIG_BIOSBASE, &agxInfoRec.xconfigFlag) ) {
            agxInfoRec.COPbase = agxInfoRec.BIOSbase
                                 + POS_CONF_COPROC_REG_OFF
                                 + agxInfoRec.instance * 0x80;
      }
      else if( agxInfoRec.COPbase == 0 ) {
            agxInfoRec.COPbase = GE_DEF_MEM_BASE;
            agxInfoRec.COPbase += agxInfoRec.instance << 7;
      }
   }
   ErrorF( "%s %s: Coprocessor Memory-Mapped Register Base Address = 0x%05x \
(COPBASE)\n",
            OFLG_ISSET(XCONFIG_COPBASE, &agxInfoRec.xconfigFlag) 
            || OFLG_ISSET(XCONFIG_BIOSBASE, &agxInfoRec.xconfigFlag)
               ? XCONFIG_GIVEN : XCONFIG_PROBED,
            agxInfoRec.name, agxInfoRec.COPbase );

   /* map the coprocessor memory-mapped registers */
   agxGEPhysBase = (pointer) agxInfoRec.COPbase;
   agxGEBase = xf86MapVidMem( agxInfoRec.scrnIndex, LINEAR_REGION,
                              (pointer)((unsigned int)agxGEPhysBase & 0xFFF000),
                               0x1000 );
   agxGEBase = (void *)((unsigned int)agxGEBase +
			((unsigned int)agxGEPhysBase & 0x0FFF));
   xf86MapDisplay(agxInfoRec.scrnIndex, LINEAR_REGION); 

   /* determine coprocessor's video memory address base */
   agxMemBase = agxInfoRec.MemBase;
   if (xf86Verbose) {
      ErrorF( "%s %s: Coprocessor's Video Memory Base Address = 0x%06x \
(MEMBASE)\n",
            OFLG_ISSET(XCONFIG_MEMBASE, &agxInfoRec.xconfigFlag) 
               ? XCONFIG_GIVEN : XCONFIG_PROBED,
            agxInfoRec.name, agxMemBase );
   }

   /*
    * Set Max Clock Frequency, for the chipset
    */

   if (XGA_2_ONLY(agxChipId)) {
      /* has programmable clocks */ 
      agxClockSelectFunc = xgaNiClockSelect;  
      if( OFLG_ISSET(XCONFIG_DACSPEED, &agxInfoRec.xconfigFlag) )
         xf86MaxClock = min( MAX_XGA_NI_CLOCK, agxInfoRec.dacSpeeds[0] );
      else
         xf86MaxClock = MAX_XGA_NI_CLOCK_CONSERV;
      OFLG_SET(CLOCK_OPTION_PROGRAMABLE, &(agxInfoRec.clockOptions));
   }
   else {
      agxClockSelectFunc = agxClockSelect;
      if (AGX_16_ONLY(agxChipId))
         xf86MaxClock = MAX_AGX_16_CLOCK;
      else if (AGX_15_ONLY(agxChipId))
         xf86MaxClock = MAX_AGX_15_CLOCK;
      else if (AGX_14_ONLY(agxChipId))
         xf86MaxClock = MAX_AGX_14_CLOCK;
      else 
         xf86MaxClock = MAX_XGA_1_CLOCK;
   }
   agxInfoRec.maxClock = xf86MaxClock;

   /*
    * Handle the depth options
    */
   
   if( XGA_SERIES(agxChipId) && xf86bpp == 15 ) {
      xf86bpp = agxInfoRec.depth = 16;
   }

   if (xf86bpp < 0) {
      xf86bpp = agxInfoRec.depth;
   }
   if (xf86weight.red == 0 || xf86weight.green == 0 || xf86weight.blue == 0) {
      xf86weight = agxInfoRec.weight;
   }
   if (xf86Verbose)
      ErrorF("%s %s: Pixel Depth = %d\n", 
             XCONFIG_GIVEN, agxInfoRec.name, xf86bpp);
   switch (xf86bpp) {
   case 8:
      BytesPerPixelShift = 0;
      xf86RamDacBPP = 8;
      break;
   case 15:
      BytesPerPixelShift = 1;
      agxInfoRec.depth = 15;
      xf86bpp = 16;
      agxWeight = RGB16_555;
      xf86weight.red = xf86weight.green = xf86weight.blue = 5;
      xf86RamDacBPP = 15;
      agxInfoRec.bitsPerPixel = 16;
      if (agxInfoRec.defaultVisual < 0)
         agxInfoRec.defaultVisual = TrueColor;
      if (defaultColorVisualClass < 0)
         defaultColorVisualClass = agxInfoRec.defaultVisual;
      break;
   case 16:
      BytesPerPixelShift = 1;
      xf86weight.red = xf86weight.blue = 5;
      xf86weight.green = 6;
      agxWeight = RGB16_565;
      agxInfoRec.depth = 16;
      xf86RamDacBPP = 16;
      agxInfoRec.bitsPerPixel = 16;
      if (agxInfoRec.defaultVisual < 0)
         agxInfoRec.defaultVisual = TrueColor;
      if (defaultColorVisualClass < 0)
         defaultColorVisualClass = agxInfoRec.defaultVisual;
      break;
#ifdef AGX_32BPP
   case 24:
   case 32:
      BytesPerPixelShift = 2;
      xf86bpp = 32;
      agxInfoRec.depth = 24;
      agxInfoRec.bitsPerPixel = 32; /* Use sparse 24 bpp (RGBX) */
      xf86RamDacBPP = 32;
      agxWeight = RGB32_888;
      /* s3MaxClock = S3_MAX_32BPP_CLOCK; */
      xf86weight.red =  xf86weight.green = xf86weight.blue = 8;
      if (agxInfoRec.defaultVisual < 0)
         agxInfoRec.defaultVisual = TrueColor;
      if (defaultColorVisualClass < 0)
         defaultColorVisualClass = agxInfoRec.defaultVisual;
      break;
#endif
   default:
#ifdef AGX_32BPP
      ErrorF(
        "Invalid value for bpp.  Valid values are 8, 15, 16, 24 and 32.\n");
#else
      ErrorF(
        "Invalid value for bpp.  Valid values are 8, 15, and 16.\n");
#endif
      xf86DisableIOPorts(agxInfoRec.scrnIndex);
      return(FALSE);
   }

   if (agxInfoRec.bitsPerPixel > 8 &&
       defaultColorVisualClass >= 0 && defaultColorVisualClass != TrueColor) {
      ErrorF("Invalid default visual type: %d (%s)\n", defaultColorVisualClass,
             xf86VisualNames[defaultColorVisualClass]);
      xf86DisableIOPorts(agxInfoRec.scrnIndex);
      return(FALSE);
   }

   /*
    * Save the VGA state
    */
   agxSavedState = agxHWSave(agxSavedState, sizeof(agxSaveBlock));
   agxClearColor0();
   outb(agxIdxReg, 0);
   if(XGA_PALETTE_CONTROL(agxChipId)) {
      outb(agxIdxReg, IR_PAL_MASK);
      outb(agxByteData, 0x00);
   }
   else {
      outb(VGA_PAL_MASK, 0x00);
   }

   /* 
    * The Hercules specific routines are also generic for accessing
    * RAMDAC registers 0-7.
    */
   xf86OutRamDacReg  = hercOutRamDacReg;
   xf86OutRamDacData = hercOutRamDacData;
   xf86InRamDacReg   = hercInRamDacReg;

   /*
    * Handle RAMDAC Option flags.
    */
   

   if(AGX_SERIES(agxChipId)) {
      /* Default is 8-bit DAC -- unless default "NORMAL" RAMDAC (handled below) */ 
      if (OFLG_ISSET(OPTION_DAC_8_BIT, &agxInfoRec.options)) {
         xf86Dac8Bit = TRUE;
      }
      else if (OFLG_ISSET(OPTION_DAC_6_BIT, &agxInfoRec.options)) {
         xf86Dac8Bit = FALSE;
      }
      else {
         xf86Dac8Bit = TRUE;
      }
   }
   else
      xf86Dac8Bit = TRUE;


   if(AGX_SERIES(agxChipId)) {

      if (agxInfoRec.ramdac) {
         xf86RamDacType = xf86StringToToken(agxDacTable, agxInfoRec.ramdac);
         if (xf86RamDacType < 0 && AGX_SERIES(agxChipId)) {
            ErrorF("%s %s: Unknown RAMDAC type \"%s\"\n", XCONFIG_GIVEN,
                   agxInfoRec.name, agxInfoRec.ramdac);
            xf86RamDacType = NORMAL_DAC; 
         }
         else {
            ErrorF("%s %s: RAMDAC type: \"%s\"\n", XCONFIG_GIVEN,
                   agxInfoRec.name, agxInfoRec.ramdac);
         }
      }

      if( xf86RamDacType == HERC_DUAL_DAC
          || xf86RamDacType == HERC_SMALL_DAC ) {
         hercProbeRamDac();
      }

      if( xf86RamDacType == NORMAL_DAC ) {
         /* Default needs to be 6 bit */
         if (OFLG_ISSET(OPTION_DAC_8_BIT, &agxInfoRec.options)) {
            xf86Dac8Bit = TRUE;
         }
         else {
            xf86Dac8Bit = FALSE;
         }
      }

      xf86DacSyncOnGreen = FALSE;
      if ( DAC_IS_BT485_SERIES || DAC_IS_BT481_SERIES || DAC_IS_ATT490 ) {
         if (OFLG_ISSET(OPTION_SYNC_ON_GREEN, &agxInfoRec.options)) {
            xf86DacSyncOnGreen = TRUE;
            if (xf86Verbose)
            ErrorF("%s %s: Putting RAMDAC into sync-on-green mode\n",
                   XCONFIG_GIVEN, agxInfoRec.name);
         } 
      }
   }
   else {
      xf86RamDacType = XGA_DAC;
   }

   if( !hercBigDAC && !hercSmallDAC )
      xf86SetUpRamDac();

   agxInfoRec.maxClock = xf86MaxClock;

   /* do we need to probe? */
   if( !agxInfoRec.videoRam 
       || agxClockSelectFunc != xgaNiClockSelect
          && !agxInfoRec.clocks ) {
      agxClearColor0();
      outb(agxIdxReg, 0);
      if(XGA_PALETTE_CONTROL(agxChipId)) {
         outb(agxIdxReg, IR_PAL_MASK);
         outb(agxByteData, 0x00);
      }
      else {
         outb(VGA_PAL_MASK, 0x00);
      }
      if( agxClockSelectFunc == xgaNiClockSelect )  
         agxInfoRec.clock[0] = 25000;
      agxSetUpProbeCRTC( &agxProbeCRTC ); 
      agxSetCRTCRegs(&agxProbeCRTC);
      agxInitGE();
      if (!agxInfoRec.videoRam) {
         agxInfoRec.videoRam = agxGetMemSize();
         if (agxInfoRec.videoRam == 0 )
            ErrorF("%s %s: Video memory probe failed, specify the \
   memory size in your XF86Config file.\n",
                   XCONFIG_PROBED, agxInfoRec.name);
      }
   
      /*
       * Get the clocks
       */
      if (agxClockSelectFunc != xgaNiClockSelect) {
         if (!agxInfoRec.clocks) {
            agxProbeClocks(1);
         }
         else if( hercBigDAC && agxInfoRec.clocks > 16 ) {
            ErrorF("%s %s: WARNING!!! Clocks have changed since 3.1.1 \
(see README.agx)\n",
                   XCONFIG_GIVEN, agxInfoRec.name);
            return FALSE;
         }
         else if (agxInfoRec.clocks > 16) {
            agxInfoRec.clocks = 16;
         }
      }
   
      outb(agxIdxReg, 0);
      if(XGA_PALETTE_CONTROL(agxChipId)) {
         outb(agxIdxReg, IR_PAL_MASK);
         outb(agxByteData, 0xFF);
      }
      else {
         outb(VGA_PAL_MASK, 0xFF);
      }
   }
   
   agxHWRestore(agxSavedState);
   
   xf86DisableIOPorts(agxInfoRec.scrnIndex);

   /*
    * Adjust the clocks for depth
    */
   if( hercBigDAC ) {
      /* for 2MB Graphites */
      if( agxInfoRec.depth == 8 ) {
          hercAddDoubledClocks(&agxInfoRec);
      }
      else if( agxInfoRec.depth > 16 ) {
          int clk, max;
          max = agxInfoRec.clocks;
          for( clk=0; clk < max; clk++ )
             agxInfoRec.clock[clk] >>= 1;
      }
      hercValidateClocks(&agxInfoRec) ; 
   } 
   else {
      switch( agxInfoRec.depth ) {
         int clk, max;
         case 8:
            break;
   
         case 15:
         case 16:
            max = agxInfoRec.clocks;
            for( clk=0; clk < max; clk++ )
               agxInfoRec.clock[clk] >>= 1;
            break;
   
         case 24:
         case 32:
            max = agxInfoRec.clocks;
            for( clk=0; clk < max; clk++ )
               agxInfoRec.clock[clk] >>= 2;
            break;
      }
   }

   if (xf86Verbose) {
      int i;

      ErrorF("%s ",OFLG_ISSET(XCONFIG_CLOCKS,&agxInfoRec.xconfigFlag)
                      ? XCONFIG_GIVEN : XCONFIG_PROBED);
      ErrorF("%s: ", agxInfoRec.name);

      if(OFLG_ISSET(CLOCK_OPTION_PROGRAMABLE,&(agxInfoRec.clockOptions)))
         ErrorF("Dot-clocks at %d bpp: Programmable", agxInfoRec.depth);
      else
         ErrorF("Dot-clocks at %d bpp: %d", 
                 agxInfoRec.depth, agxInfoRec.clocks );

      for (i = 0; i < agxInfoRec.clocks; i++) {
         if (i % 8 == 0)
            ErrorF("\n%s %s:            ",
                   OFLG_ISSET(XCONFIG_CLOCKS,&agxInfoRec.xconfigFlag)
                   ? XCONFIG_GIVEN : XCONFIG_PROBED,
                   agxInfoRec.name);
            ErrorF(" %6.2f", agxInfoRec.clock[i]/1000.0);
      }
      ErrorF("\n");
   }


   tx = agxInfoRec.virtualX;
   ty = agxInfoRec.virtualY;
   pMode = pEnd = agxInfoRec.modes;
   if( pMode == NULL ) {
      ErrorF("No modes supplied in XF86Config\n");
      return FALSE;
   } 
   pEnd = NULL;
   do {
      DisplayModePtr pModeSv;

      pModeSv = pMode->next;
      /*
       * xf86LookupMode returns FALSE if it ran into an invalid
       * parameter 
       */
      if (!xf86LookupMode(pMode, &agxInfoRec, LOOKUP_DEFAULT)) {
         xf86DeleteMode(&agxInfoRec, pMode);
      }
      else {
         if (pMode->HDisplay > 2048) {
            ErrorF("%s %s: Width of mode \"%s\" is too large (max is %d)\n",
                   XCONFIG_PROBED, agxInfoRec.name, pMode->name, 2048);
            xf86DeleteMode(&agxInfoRec, pMode);
         }
         else if ( (pMode->HDisplay * (1 + pMode->VDisplay))
                    > agxInfoRec.videoRam * 1024) {
            ErrorF("%s %s: Too little memory for mode \"%s\"\n", XCONFIG_PROBED,
                   agxInfoRec.name, pMode->name);
            xf86DeleteMode(&agxInfoRec, pMode);
         }
         else if (((tx > 0) && (pMode->HDisplay > tx)) ||
                    ((ty > 0) && (pMode->VDisplay > ty))) {
            ErrorF("%s %s: Resolution %dx%d too large for virtual %dx%d\n",
                   XCONFIG_PROBED, agxInfoRec.name,
                   pMode->HDisplay, pMode->VDisplay, tx, ty);
            xf86DeleteMode(&agxInfoRec, pMode);
         }
         else {
            /*
             * Successfully looked up this mode.  If pEnd isn't
             * initialized, set it to this mode.
             */
            if (pEnd == (DisplayModePtr) NULL)
               pEnd = pMode;
   
            agxInfoRec.virtualX = max( agxInfoRec.virtualX, pMode->HDisplay );
            agxInfoRec.virtualY = max( agxInfoRec.virtualY, pMode->VDisplay );
         }
      }
      pMode = pModeSv;
   } while (pMode != pEnd);

   if ((tx != agxInfoRec.virtualX) || (ty != agxInfoRec.virtualY))
      OFLG_CLR(XCONFIG_VIRTUAL,&agxInfoRec.xconfigFlag);

   agxVirtX = agxInfoRec.virtualX;
   agxVirtY = agxInfoRec.virtualY;

   /*
    * AGX -014,-015,-016 and XGA display map width must be power of
    * 2, if the coprocessor is to be used, except that the -015
    * and later have a +256 adjust. The -016 has some additional
    * adjusts for 640 and 800. The XGA's (AGX-10) also appear to 
    * have the similiar limits as the -016
    */
   agx128WidthAdjust = FALSE;
   agx256WidthAdjust = FALSE;
   agx288WidthAdjust = FALSE;
   if (XGA_SERIES(agxChipId) && agxVirtX <= 320 ) {
      agxAdjustedVirtX = 320;
      agxDisplayWidth = 320;
   }
   else
   if (agxVirtX <= 512) {
      agxAdjustedVirtX = 512;
      agxDisplayWidth = 512;
   }
   else
   if (AGX_16_ONLY(agxChipId) && agxVirtX <= 640) {
      agx128WidthAdjust = TRUE;
      agxAdjustedVirtX = 512;
      agxDisplayWidth = 640;
   }
   else
   if (AGX_10_XGA_ONLY(agxChipId) && agxVirtX <= 640) {
      agxAdjustedVirtX = 640;
      agxDisplayWidth = 640;
   }
   else
   if (AGX_16_ONLY(agxChipId) && agxVirtX <= 800) {
      agx288WidthAdjust = TRUE;
      agxAdjustedVirtX = 512;
      agxDisplayWidth = 800;
   }
   else
   if (AGX_10_XGA_ONLY(agxChipId) && agxVirtX <= 800) {
      agxAdjustedVirtX = 800;
      agxDisplayWidth = 800;
   }
   else
   if (agxVirtX <= 1024) {
      agxAdjustedVirtX = 1024;
      agxDisplayWidth = 1024;
   }
   else
   if (AGX_10_XGA_ONLY(agxChipId) && agxVirtX <= 1152) {
      agxAdjustedVirtX = 1152;
      agxDisplayWidth = 1152;
   }
   else
   if (AGX_15_16_ONLY(agxChipId) && agxVirtX <= 1280) {
      agx256WidthAdjust = TRUE;
      agxAdjustedVirtX = 1024;
      agxDisplayWidth = 1280;
   }
   else
   if (AGX_10_XGA_ONLY(agxChipId) && agxVirtX <= 1280) {
      agxAdjustedVirtX = 1280;
      agxDisplayWidth = 1280;
   }
   else
   if (agxVirtX <= 2048) {
      agxAdjustedVirtX = 2048;
      agxDisplayWidth = 2048;
   }

   agxMaxX = agxVirtX - 1;
   agxMaxY = agxVirtY - 1;

   if (xf86Verbose) {
      ErrorF("%s %s: Virtual resolution = %dx%d, CRTC Line Width = %d\n",
	     OFLG_ISSET(XCONFIG_VIRTUAL, &agxInfoRec.xconfigFlag)
                ? XCONFIG_GIVEN : XCONFIG_PROBED,
	     agxInfoRec.name, agxVirtX, agxVirtY, agxDisplayWidth);
   }

    /* Set agxMemorySize to required MEM_SIZE value in MISC_OPTIONS */
   if (agxInfoRec.videoRam <= 512)
      agxMemorySize = MEM_SIZE_512K;
   else if (agxInfoRec.videoRam <= 1024)
      agxMemorySize = MEM_SIZE_1M;
   else if (agxInfoRec.videoRam <= 2048)
      agxMemorySize = MEM_SIZE_2M;
   else
      agxMemorySize = MEM_SIZE_4M;

   if (xf86Verbose) {
      ErrorF("%s %s: Videoram = %dk\n",
	     OFLG_ISSET(XCONFIG_VIDEORAM, &agxInfoRec.xconfigFlag)
	        ? XCONFIG_GIVEN : XCONFIG_PROBED, 
             agxInfoRec.name,
	     agxInfoRec.videoRam );
   }

   if ( ((xf86bpp * (agxDisplayWidth*agxVirtY)) >> 3) 
        > (agxInfoRec.videoRam<<10) ) {
      ErrorF(
         "%s %s: Not enough memory for requested CRTC resolution (%dx%d).\n",
         XCONFIG_PROBED, agxInfoRec.name,
         agxDisplayWidth, agxVirtY );
      return FALSE;
   }

   {
     unsigned long end = ((xf86bpp * (agxDisplayWidth*agxVirtY)) >> 3);
     unsigned long avail;
     unsigned long total = agxInfoRec.videoRam << 10;
 
     /* align to 64K -- 16K for the XGA */
     if( AGX_10_XGA_ONLY(agxChipId) )  
        agxScratchOffset = (end + 0x3FFF) & 0xFFFFC000;
     else
        agxScratchOffset = (end + 0xFFFF) & 0xFFFF0000;
     avail = total - agxScratchOffset;

    if( !OFLG_ISSET(OPTION_NOACCEL, &agxInfoRec.options) ) {  
        if( AGX_10_XGA_ONLY(agxChipId) 
            && avail >= 0x0C000 && avail < 0x10000 )
           agxScratchSize = 0x04000;    /* 32K Font Cache */
        else if( AGX_10_XGA_ONLY(agxChipId) && avail < 0x10000 )
           agxScratchSize = avail & 0x1C000;   /* No Font Cache */
        else if( AGX_10_XGA_ONLY(agxChipId) && avail < 0x20000 )
           agxScratchSize = 0x08000 + (avail & 0x04000);    
        else if( avail < 0x10000 )
           agxScratchSize = 0;
        else if( avail < 0x40000 )
           agxScratchSize = 0x10000 + (avail & 0x04000);
        else if( avail < 0x80000 )
           agxScratchSize = 0x20000 + (avail & 0x0C000); 
        else 
           agxScratchSize = 0x40000; 
    }
    else {
        agxScratchSize = avail; 
    }
    
    if( !OFLG_ISSET(OPTION_NOACCEL, &agxInfoRec.options) ) {  
        /* align to 64K -- 32K/64K for the XGA */
        agxFontCacheOffset = (agxScratchOffset + agxScratchSize) & 0XFF8000;
        agxFontCacheSize   = total - agxFontCacheOffset;
        if( AGX_10_XGA_ONLY(agxChipId) )  {
           if( agxFontCacheSize < 0x08000 ) {
              agxFontCacheSize   = 0;
              agxFontRowLength   = 2048; /* to prevent div-by-zero */
              agxFontRowNumLines = 0;
           }
           else if( agxFontCacheOffset & 0x08000 && agxFontCacheSize < 0x20000 ) {
              agxFontCacheSize   &= 0xFF8000;
              agxFontRowLength    = 0x008000;
              agxFontRowNumLines  = 1024;
           }
           else {
              agxFontCacheOffset &= 0xFF0000;
              agxFontCacheSize   &= 0xFF0000;
              agxFontRowLength    = 0x010000;
              agxFontRowNumLines  = 2048;
           }
        }
        else {
           agxFontCacheOffset &= 0xFF0000;
           agxFontCacheSize   &= 0xFF0000;
           agxFontRowLength    = 0x010000;
           agxFontRowNumLines  = 2048;
        }
     }
     else {
        agxFontCacheSize   = 0;
        agxFontRowLength   = 2048;
        agxFontRowNumLines = 0;
     }

     if( agxScratchSize < 0x10000 && !AGX_10_XGA_ONLY(agxChipId) ) {
         ErrorF("%s %s: 64K video memory required for scratchpad, \
0x%05x available\n",
             XCONFIG_PROBED, agxInfoRec.name, agxScratchSize );
         return FALSE; 
     }
     else if( agxScratchSize < 0x04000 && AGX_10_XGA_ONLY(agxChipId) ) {
         ErrorF("%s %s: 16K video memory required for scratchpad, \
0x%05x available\n",
             XCONFIG_PROBED, agxInfoRec.name, agxScratchSize );
         return FALSE; 
     }
     
     if (xf86Verbose) 
       ErrorF( "%s %s: ScratchPad = %dk @ offset 0x%x\n",
	       XCONFIG_PROBED, agxInfoRec.name,
               agxScratchSize>>10, agxScratchOffset );
   }

#ifdef XFreeXDGA
    agxInfoRec.physBase = (unsigned long) agxInfoRec.VGAbase;
    agxInfoRec.physBase = (unsigned long) agxPhysVidMem;
    agxInfoRec.physSize = 64 * 1024;
    agxInfoRec.displayWidth = agxDisplayWidth;
    agxInfoRec.directMode = XF86DGADirectPresent;
#endif


   return TRUE;
}


/*
 * agxPrintIdent --
 *     Print the indentification of the video card.
 */
void
agxPrintIdent()
{
    ErrorF("  %s: Accelerated server for AGX graphics adaptors ",
	   agxInfoRec.name);
    ErrorF("(Patchlevel %s)\n", agxInfoRec.patchLevel);
}

int
agxGetMemSize()
{
   char i, lastBank=-1;
   unsigned int mask;
   unsigned int tmp1, tmp2;
   volatile unsigned char *x1, *x2;

   x1 = vgaBase;
   x2 = x1 + 0xFFFC;
   xf86MapDisplay(agxInfoRec.scrnIndex, VGA_REGION); 
   for( i=0; i<0x40; i++) {
      outb( agxApIdxReg, i );
      usleep(10000);
      mask = (~i<<24) | 0x00A55A00 | i;
      MemToBus( (pointer)x1, &mask, 4);
      MemToBus( (pointer)x2, &mask, 4);
      x1 += 128;
      x2 -= 128;
   }
   x1 = vgaBase;
   x2 = x1 + 0xFFFC;
   for( i=0; i<0x40; i++ ) {
      outb( agxApIdxReg, i );
      usleep(10000);
      mask = (~i<<24) | 0x00A55A00 | i;
      BusToMem( &tmp1, (pointer)x1, 4);
      BusToMem( &tmp2, (pointer)x2, 4);
      if( tmp1 == mask && tmp2 == mask ) { 
         lastBank = i;
      }
      else {
         lastBank++;
         break;
      }
      x1 += 128;
      x2 -= 128;
   }
   outb( agxApIdxReg, 0 );
   return lastBank*0x40;
}


/*
 * agxInit --
 *      Attempt to find and initialize the Linear Framebuffer
 *      Most of the elements of the ScreenRec are filled in.  The
 *      video is enabled for the frame buffer...
 */

Bool
agxInit (scr_index, pScreen, argc, argv)
   int            scr_index;    /* The index of pScreen in the ScreenInfo */
   ScreenPtr      pScreen;      /* The Screen to initialize */
   int            argc;         /* The number of the Server's arguments. */
   char           **argv;       /* The arguments themselves. Don't change! */
{
   int displayResolution = 75;  /* default to 75dpi */
   extern int monitorResolution;

   agxImageInit();

   xf86EnableIOPorts(scr_index);

   if (vgaPhysBase) {
      xf86MapDisplay(scr_index, VGA_REGION); 
   }
   if (agxPhysVidMem != vgaPhysBase)  {
      xf86MapDisplay(scr_index, LINEAR_REGION);
   }
   xf86MapDisplay(scr_index, LINEAR_REGION);

   vgaVirtBase = (pointer)VGABASE;

   agxCalcCRTCRegs(&agxCRTCRegs, agxInfoRec.modes);

   agxInited = FALSE;
   agxInitDisplay(scr_index,&agxCRTCRegs);

   /* Clear the display.
    * Need to set the color, origin, and size.  Then draw.
    */
#ifndef DIRTY_STARTUP
   if(agxInfoRec.bitsPerPixel == 8 && xf86FlipPixels)         
      agxImageClear(1);
   else
      agxImageClear(0);
#endif
   agxBitCache8Init(agxDisplayWidth, agxVirtY);

   /*
    * Take display resolution from the -dpi flag if specified
    */

   if (monitorResolution)
      displayResolution = monitorResolution;

   if (!agxScreenInit(pScreen, 
		      (pointer) vgaVirtBase,
		      agxInfoRec.virtualX,
		      agxInfoRec.virtualY,
		      displayResolution,
		      displayResolution,
		      agxDisplayWidth))
      return(FALSE);

   pScreen->CloseScreen = agxCloseScreen;
   pScreen->SaveScreen = agxSaveScreen;

   switch (agxInfoRec.bitsPerPixel) {
        case 8:
            pScreen->InstallColormap = agxInstallColormap;
            pScreen->UninstallColormap = agxUninstallColormap;
            pScreen->ListInstalledColormaps = agxListInstalledColormaps;
            pScreen->StoreColors = agxStoreColors;
            break;
        case 16:
        case 32:
            pScreen->InstallColormap = cfbInstallColormap;
            pScreen->UninstallColormap = cfbUninstallColormap;
            pScreen->ListInstalledColormaps = cfbListInstalledColormaps;
            pScreen->StoreColors = (void (*)())NoopDDA;
        }

   if (TRUE | OFLG_ISSET(OPTION_SW_CURSOR, &agxInfoRec.options)) { 
      miDCInitialize (pScreen, &xf86PointerScreenFuncs);
   }
   else {
      pScreen->QueryBestSize = agxQueryBestSize;
      xf86PointerScreenFuncs.WarpCursor = agxWarpCursor;
      (void)agxCursorInit(0, pScreen);
   } 

   savepScreen = pScreen;

   /* enable DAC output */
   outb(agxIdxReg, 0);
   if(XGA_PALETTE_CONTROL(agxChipId)) {
      outb(agxIdxReg, IR_PAL_MASK);
      outb(agxByteData, 0xFF);
   }
   else {
      outb(VGA_PAL_MASK, 0xFF);
   }
   return cfbCreateDefColormap(pScreen);
}

/*
 * agxEnterLeaveVT -- 
 *      grab/ungrab the current VT completely.
 */

void
agxEnterLeaveVT(enter, screen_idx)
   Bool enter;
   int screen_idx;
{
   PixmapPtr pspix;
   ScreenPtr pScreen = savepScreen;
   unsigned  int  palDataReg;

#if 0
   ErrorF( "agxEnterLeaveVT() - Enter %x, screen_idx %x\n", enter, screen_idx );
   ErrorF( "agxEnterLeaveVT() - savepScreen %x\n", savepScreen );
#endif

   if ( !xf86Resetting && !xf86Exiting ) {
      switch (agxInfoRec.bitsPerPixel) {
         case 8:
            pspix = (PixmapPtr)pScreen->devPrivate;
            break;
         case 16:
            pspix =
                  (PixmapPtr)pScreen->devPrivates[cfb16ScreenPrivateIndex].ptr;
            break;
#ifdef AGX_32BPP
         case 32:
            pspix =
                  (PixmapPtr)pScreen->devPrivates[cfb32ScreenPrivateIndex].ptr;
            break;
#endif
      }
   }

   if (enter) {
#if 0
      ErrorF( "agxEnterLeaveVT() - ENTER \n");
#endif 
      xf86EnableIOPorts(screen_idx);
      if (vgaPhysBase)
	 xf86MapDisplay(screen_idx, VGA_REGION); 
#if 0 
      if (agxPhysVidMem != vgaPhysBase) 
	 xf86MapDisplay(screen_idx, LINEAR_REGION);
#endif

      xf86MapDisplay(screen_idx, LINEAR_REGION);

      if (!xf86Resetting) {
	 ScrnInfoPtr pScr = XF86SCRNINFO(pScreen);
#if 0
         ErrorF( "agxEnterLeaveVT() - ENTER  - !xf86Resetting\n");
#endif

         outb(agxIdxReg, 0);
         if( agxInfoRec.bitsPerPixel == 8 ) {
            /* make sure screen is blanked during setup */
            if(XGA_PALETTE_CONTROL(agxChipId)) {
               outb(agxIdxReg, IR_CUR_PAL_INDEX_LO);
               outb(agxByteData, 0x00);
               outb(agxIdxReg, IR_PAL_DATA);
               palDataReg = agxByteData;
            }
            else {
               outb(agxIdxReg, 0);  /* make sure index is not 0x51 */
               outb(VGA_PAL_WRITE_INDEX, 0x00);
               palDataReg = VGA_PAL_DATA;
            }
            outb(palDataReg, 0);
            outb(palDataReg, 0);
            outb(palDataReg, 0);
         }
         if(XGA_PALETTE_CONTROL(agxChipId)) {
            outb(agxIdxReg, IR_PAL_MASK);
            outb(agxByteData, 0x00);
         }
         else {
            outb(VGA_PAL_MASK, 0x00);
         }

         agxCalcCRTCRegs(&agxCRTCRegs, agxInfoRec.modes);
         agxInited = FALSE;
         agxInitDisplay(screen_idx,&agxCRTCRegs);

         /* Clear the display.
          * Need to set the color, origin, and size.  Then draw.
          */
#ifndef DIRTY_STARTUP
         if( agxInfoRec.bitsPerPixel == 8 )
            agxImageClear(1);
         else
            agxImageClear(0);
#endif
  	 agxBitCache8Init(agxDisplayWidth, agxVirtY);
  	 agxRestoreCursor(pScreen);
  	 agxAdjustFrame(pScr->frameX0, pScr->frameY0);
#if 0
         ErrorF( "agxEnterLeaveVT() - ENTER - pspix->devPrivate.ptr %x\n", 
                 pspix->devPrivate.ptr );
         ErrorF( "agxEnterLeaveVT() - ENTER - vgaVirtBase %x\n", 
                 vgaVirtBase );
         ErrorF( "agxEnterLeaveVT() - ENTER - ppix %x\n", ppix);
#endif
	 if ( (pointer)pspix->devPrivate.ptr != (pointer)vgaVirtBase && ppix ) {
	    pspix->devPrivate.ptr = vgaVirtBase;
            GE_WAIT_IDLE();
#if 0
            ErrorF( "agxEnterLeaveVT() - DisplayWidth %d, pScreen->width %d, depth %d\n",
                    agxDisplayWidth, pScreen->width, pScreen->rootDepth);
            ErrorF( "agxEnterLeaveVT() - ENTER - agxImageWriteFunc %x\n", ppix);
#endif
            (*agxImageWriteFunc)( 0, 0, 
                                  pScreen->width, pScreen->height,
		 	          ppix->devPrivate.ptr,
				  PixmapBytePad( agxDisplayWidth,
					         pScreen->rootDepth ),
				  0, 0, MIX_SRC, ~0 );
	 }
	 if (LUTissaved) {
	    agxRestoreLUT(agxsavedLUT);
	    LUTissaved = FALSE;
	    /*agxRestoreColor0(pScreen);*/
	 }

         outb(agxIdxReg, 0);
         if(XGA_PALETTE_CONTROL(agxChipId)) {
            outb(agxIdxReg, IR_PAL_MASK);
            outb(agxByteData, 0xFF);
         }
         else {
            outb(VGA_PAL_MASK, 0xFF);
         }
      }
      if (ppix) {
	 (pScreen->DestroyPixmap)(ppix);
	 ppix = NULL;
      }
   } 
   else {
#if 0
      ErrorF( "agxEnterLeaveVT() - EXIT \n");
#endif
      xf86EnableIOPorts(screen_idx);
      if (vgaPhysBase)
	 xf86MapDisplay(screen_idx, VGA_REGION);
#if 0
      if (agxPhysVidMem != vgaPhysBase) 
	 xf86MapDisplay(screen_idx, LINEAR_REGION);
#endif

      xf86MapDisplay(screen_idx, LINEAR_REGION);

      if (!xf86Exiting) {

         /*
          * Create a dummy pixmap to write to while VT is switched out.
          * Copy the screen to that pixmap
          */
#if 0
         ErrorF( "agxEnterLeaveVT() - EXIT  - !xf86Exiting\n");
#endif

	 ppix = (pScreen->CreatePixmap)(pScreen,
					agxDisplayWidth, pScreen->height,
					pScreen->rootDepth);
#if 0
         ErrorF( "agxEnterLeaveVT() - DisplayWidth %d, pScreen->width %d, depth %d\n",
                  agxDisplayWidth, pScreen->width, pScreen->rootDepth);
         ErrorF( "agxEnterLeaveVT() - EXIT  - ppix %x\n", ppix);
         ErrorF( "agxEnterLeaveVT() - EXIT  - pspix %x\n", pspix);
#endif
	 if (ppix) {
#if 0
            ErrorF( "agxEnterLeaveVT() - EXIT  - agxImageReadFunc %x\n", ppix);
#endif
            GE_WAIT_IDLE();
   	    (agxImageReadFunc)( 0, 0, 
				pScreen->width, pScreen->height,
				ppix->devPrivate.ptr,
				PixmapBytePad( agxDisplayWidth,
					       pScreen->rootDepth ),
				0, 0, ~0 );
            pspix->devPrivate.ptr = ppix->devPrivate.ptr;
	 }
      }
      
#if 0
   ErrorF( "agxEnterLeaveVT() - LUT\n");
#endif
#if 0
      agxCursorOff();
#endif
      agxSaveLUT(agxsavedLUT);
      LUTissaved = TRUE;

      outb(agxIdxReg, 0);  /* make sure index is not 0x51 */
      if( agxInfoRec.bitsPerPixel == 8
#ifdef XFreeXDGA
           && (!(agxInfoRec.directMode & XF86DGADirectGraphics))
#endif
      ) {
         /* make sure screen is blanked during exit */
         if(XGA_PALETTE_CONTROL(agxChipId)) {
            outb(agxIdxReg, IR_CUR_PAL_INDEX_LO);
            outb(agxByteData, 0x00);
            outb(agxIdxReg, IR_PAL_DATA);
            palDataReg = agxByteData;
         }
         else {
            outb(VGA_PAL_WRITE_INDEX, 0x00);
            palDataReg = VGA_PAL_DATA;
         }
         outb(palDataReg, 0);
         outb(palDataReg, 0);
         outb(palDataReg, 0);
         if(XGA_PALETTE_CONTROL(agxChipId)) {
            outb(agxIdxReg, IR_PAL_MASK);
            outb(agxByteData, 0x00);
         }
         else {
            outb(VGA_PAL_MASK, 0x00);
         }
      }

      if (!xf86Resetting) {

#ifdef XFreeXDGA
          if (!(agxInfoRec.directMode & XF86DGADirectGraphics)) {
#endif
             if( agxInfoRec.bitsPerPixel == 8 ) {
                /* make sure screen is blanked during exit */
                if(XGA_PALETTE_CONTROL(agxChipId)) {
                   outb(agxIdxReg, IR_CUR_PAL_INDEX_LO);
                   outb(agxByteData, 0x00);
                   outb(agxIdxReg, IR_PAL_DATA);
                   palDataReg = agxByteData;
                }
                else {
                   outb(VGA_PAL_WRITE_INDEX, 0x00);
                   palDataReg = VGA_PAL_DATA;
                }
                outb(palDataReg, 0);
                outb(palDataReg, 0);
                outb(palDataReg, 0);
                if(XGA_PALETTE_CONTROL(agxChipId)) {
                    outb(agxIdxReg, IR_PAL_MASK);
                    outb(agxByteData, 0x00);
                }
                else {
                    outb(VGA_PAL_MASK, 0x00);
                }
             }

             agxCleanUp();
#ifdef XFreeXDGA
          } 
#endif
      }

      if (vgaPhysBase)
         xf86UnMapDisplay(screen_idx, VGA_REGION);
#if 0
      if (agxPhysVidMem != vgaPhysBase)
         xf86UnMapDisplay(screen_idx, LINEAR_REGION);
#endif

      xf86UnMapDisplay(screen_idx, LINEAR_REGION);
   }
#if 0
   ErrorF( "agxEnterLeaveVT() - exiting\n");
#endif
}

/*
 * agxCloseScreen --
 *      called to ensure video is enabled when server exits.
 */

Bool
agxCloseScreen(screen_idx, pScreen)
   int screen_idx;
   ScreenPtr pScreen;
{
   /*
    * Hmm... The server may shut down even if it is not running on the
    * current vt. Let's catch this case here.
    */
   xf86Exiting = TRUE;
   if (xf86VTSema)
      agxEnterLeaveVT(LEAVE, screen_idx);
   else if (ppix) {
      /* 7-Jan-94 CEG: The server is not running on the current vt.
       * Free the screen snapshot taken when the server vt was left.
       */
      (savepScreen->DestroyPixmap)(ppix);
      ppix = NULL;
   }
#if 0 
   savepScreen = NULL;
   agxClearSavedCursor(screen_idx);
#endif
   return(TRUE);
}

/*
 * agxSaveScreen --
 *      blank the screen.
 */

Bool
agxSaveScreen (pScreen, on)
   ScreenPtr     pScreen;
   Bool          on;
{
   unsigned char oldIndex;
   unsigned int  palDataReg;
   static PixmapPtr savePix = NULL;

   if (on)
      SetTimeSinceLastInputEvent();

   if (xf86VTSema || savePix) {
      xf86EnableIOPorts(agxInfoRec.scrnIndex);
      if (vgaPhysBase)
         xf86MapDisplay(agxInfoRec.scrnIndex, VGA_REGION);
      if (agxPhysVidMem != vgaPhysBase) 
         xf86MapDisplay(agxInfoRec.scrnIndex, LINEAR_REGION);

      xf86MapDisplay(agxInfoRec.scrnIndex, LINEAR_REGION);

      GE_WAIT_IDLE();

      oldIndex = inb(agxIdxReg);
      if( agxInfoRec.bitsPerPixel == 8 ) {
         if (on) {
            agxBitCache8Init(agxDisplayWidth, agxVirtY);

            agxRestoreColor0(pScreen);
            if(XGA_PALETTE_CONTROL(agxChipId)) {
               outb(agxIdxReg, IR_PAL_MASK);
               outb(agxByteData, 0xff);
            }
            else {
               outb(VGA_PAL_MASK, 0xff);
            }
         }
         else {
            agxClearColor0();
            if(XGA_PALETTE_CONTROL(agxChipId)) {
               outb(agxIdxReg, IR_PAL_MASK);
               outb(agxByteData, 0x00);
            }
            else {
               outb(VGA_PAL_MASK, 0x00);
            }
         }
      }
      else {
         PixmapPtr pspix;
         ScreenPtr pScreen = savepScreen;

         switch (agxInfoRec.bitsPerPixel) {
            case 8:
               pspix = (PixmapPtr)pScreen->devPrivate;
               break;
            case 16:
               pspix = (PixmapPtr)pScreen->
                           devPrivates[cfb16ScreenPrivateIndex].ptr;
               break;
#ifdef AGX_32BPP
            case 32:
               pspix = (PixmapPtr)pScreen->
                          devPrivates[cfb32ScreenPrivateIndex].ptr;
            break;
#endif
         }

         if (on) {
            ScrnInfoPtr pScr = XF86SCRNINFO(pScreen);

            agxBitCache8Init(agxDisplayWidth, agxVirtY);
            agxRestoreCursor(pScreen);
            agxAdjustFrame(pScr->frameX0, pScr->frameY0);

            if( (pointer)pspix->devPrivate.ptr != (pointer)vgaVirtBase
                && savePix != NULL
              ) {

               (*agxImageWriteFunc)( 0, 0, 
                                     pScreen->width, pScreen->height,
                                     savePix->devPrivate.ptr,
                                     PixmapBytePad( agxDisplayWidth,
                                                    pScreen->rootDepth ),
                                     0, 0, MIX_SRC, ~0 );
               (pScreen->DestroyPixmap)(savePix);
               savePix = NULL;
               xf86VTSema = TRUE;
               pspix->devPrivate.ptr = vgaVirtBase;
            }
         }
         else {
            if( savePix == NULL ) {
               savePix = (pScreen->CreatePixmap)( pScreen,
                                                  agxDisplayWidth,
                                                  pScreen->height,
                                                  pScreen->rootDepth );


               (agxImageReadFunc)( 0, 0,
                                   pScreen->width, pScreen->height,
                                   savePix->devPrivate.ptr,
                                   PixmapBytePad( agxDisplayWidth,
                                                  pScreen->rootDepth ),
                                   0, 0, ~0 );
               agxImageClear(0);

               pspix->devPrivate.ptr = savePix->devPrivate.ptr;
               xf86VTSema = FALSE;  
            }
         }
      }
      outb(agxIdxReg, oldIndex); 
   }
   return(TRUE);
}

/*
 * agxAdjustFrame --
 *      Modify the CRT_OFFSET for panning the display.
 */
void
agxAdjustFrame(x, y)
   int x, y;
{
   unsigned int byte_offset;
   /*
    * XGA and AGX are documented as being offset in units of 8.
    * But, the AGX is actually offset in units of 4.
    */
   if( AGX_SERIES(agxChipId) ) {
      byte_offset = AGX_PIXEL_ADJUST( x + y*agxDisplayWidth ) >> 2; 
   }
   else {
      byte_offset = AGX_PIXEL_ADJUST(x + y*agxDisplayWidth ) >> 3;
   }
                    
   xf86EnableIOPorts(agxInfoRec.scrnIndex);
   if (vgaPhysBase)
      xf86MapDisplay(agxInfoRec.scrnIndex, VGA_REGION); 
   if (agxPhysVidMem != vgaPhysBase) 
      xf86MapDisplay(agxInfoRec.scrnIndex, LINEAR_REGION);
   xf86MapDisplay(agxInfoRec.scrnIndex, LINEAR_REGION);

   /*agxCursorOff();*/ 
   outb(agxIdxReg, IR_DISP_MAP_LO);
   outb(agxByteData, byte_offset & 0xff);
   byte_offset >>= 8;
   outb(agxIdxReg, IR_DISP_MAP_MID);
   outb(agxByteData, byte_offset & 0xff);
   byte_offset >>= 8;
   outb(agxIdxReg, IR_DISP_MAP_HI);
   outb(agxByteData, byte_offset & 0x0f);
   /*agxRepositionCursor(savepScreen); */

#if 0 /* Is the following correct? */
#ifdef XFreeXDGA
   if (agxInfoRec.directMode & XF86DGADirectGraphics) {
      /* Wait until vertical retrace is in progress. */
      while (inb(vgaIOBase + 0xA) & 0x08);
      while (!(inb(vgaIOBase + 0xA) & 0x08));
   }
#endif
#endif
}

/*
 * agxValidMode --
 *
 */
static int
agxValidMode(mode, verbose, flag)
DisplayModePtr mode;
Bool verbose;
int flag;
{
return MODE_OK;
}
