#include "ati.h"
#include "atiadapter.h"
#include "atiadjust.h"
#include "atiaudio.h"
#include "atibus.h"
#include "atichip.h"
#include "aticonfig.h"
#include "aticursor.h"
#include "atidac.h"
#include "atidsp.h"
#include "atii2c.h"
#include "atiident.h"
#include "atiload.h"
#include "atilock.h"
#include "atimach64.h"
#include "atimach64accel.h"
#include "atimach64io.h"
#include "atimode.h"
#include "atipreinit.h"
#include "atiprint.h"
#include "atividmem.h"
#include "atiwonderio.h"
#include "atixv.h"
#include "vbe.h"
#include "xf86RAC.h"
#ifndef AVOID_CPIO
typedef CARD16 Colour;
static const Colour Test_Pixel[] = {0x5AA5U, 0x55AAU, 0xA55AU, 0xCA53U};
static const struct
{
int videoRamSize;
int Miscellaneous_Options_Setting;
struct
{
short int x, y;
}
Coordinates[NumberOf(Test_Pixel) + 1];
}
Test_Case[] =
{
{4096, MEM_SIZE_4M, {{0,0}, {0,1024}, {-1,-1}}},
{2048, MEM_SIZE_2M, {{0,0}, {0,512}, {2,0}, {3,0}, {-1,-1}}},
{1024, MEM_SIZE_1M, {{0,0}, {0,256}, {1,0}, {-1,-1}}},
{512, MEM_SIZE_512K, {{-1,-1}}}
};
static Colour
ATIMach32ReadPixel
(
const short int X,
const short int Y
)
{
Colour Pixel_Colour;
ProbeWaitIdleEmpty();
ATIWaitQueue(7);
outw(RD_MASK, (CARD16)(~0));
outw(DP_CONFIG, FG_COLOR_SRC_BLIT | DATA_WIDTH | DRAW | DATA_ORDER);
outw(CUR_X, X);
outw(CUR_Y, Y);
outw(DEST_X_START, X);
outw(DEST_X_END, X + 1);
outw(DEST_Y_END, Y + 1);
ATIWaitQueue(16);
WaitDataReady();
Pixel_Colour = inw(PIX_TRANS);
ProbeWaitIdleEmpty();
return Pixel_Colour;
}
static void
ATIMach32WritePixel
(
const short int X,
const short int Y,
const Colour Pixel_Colour
)
{
ATIWaitQueue(9);
outw(WRT_MASK, (CARD16)(~0));
outw(DP_CONFIG, FG_COLOR_SRC_FG | DRAW | READ_WRITE);
outw(ALU_FG_FN, MIX_FN_PAINT);
outw(FRGD_COLOR, Pixel_Colour);
outw(CUR_X, X);
outw(CUR_Y, Y);
outw(DEST_X_START, X);
outw(DEST_X_END, X + 1);
outw(DEST_Y_END, Y + 1);
}
static int
ATIMach32videoRam
(
void
)
{
CARD16 clock_sel, mem_bndry, misc_options, ext_ge_config;
Colour saved_Pixel[NumberOf(Test_Pixel)];
unsigned int Case_Number, Pixel_Number;
Bool AllPixelsOK;
clock_sel = inw(CLOCK_SEL);
mem_bndry = inw(MEM_BNDRY);
misc_options = inw(MISC_OPTIONS) & ~MEM_SIZE_ALIAS;
ext_ge_config = inw(R_EXT_GE_CONFIG);
ATIWaitQueue(7);
outw(CLOCK_SEL, clock_sel | DISABPASSTHRU);
outw(MEM_BNDRY, mem_bndry & ~(MEM_PAGE_BNDRY | MEM_BNDRY_ENA));
outw(MISC_OPTIONS, misc_options | MEM_SIZE_4M);
outw(EXT_GE_CONFIG, PIXEL_WIDTH_16 | ORDER_16BPP_565 | MONITOR_8514 |
ALIAS_ENA);
outw(GE_PITCH, 1024 >> 3);
outw(GE_OFFSET_HI, 0);
outw(GE_OFFSET_LO, 0);
for (Case_Number = 0;
Case_Number < (NumberOf(Test_Case) - 1);
Case_Number++)
{
# define TestPixel Test_Case[Case_Number].Coordinates[Pixel_Number]
# define ForEachTestPixel \
for (Pixel_Number = 0; TestPixel.x >= 0; Pixel_Number++)
ForEachTestPixel
saved_Pixel[Pixel_Number] =
ATIMach32ReadPixel(TestPixel.x, TestPixel.y);
ForEachTestPixel
ATIMach32WritePixel(TestPixel.x, TestPixel.y,
Test_Pixel[Pixel_Number]);
AllPixelsOK = TRUE;
ForEachTestPixel
{
if (ATIMach32ReadPixel(TestPixel.x, TestPixel.y) !=
Test_Pixel[Pixel_Number])
{
AllPixelsOK = FALSE;
break;
}
}
ForEachTestPixel
ATIMach32WritePixel(TestPixel.x, TestPixel.y,
saved_Pixel[Pixel_Number]);
if (AllPixelsOK)
break;
# undef ForEachTestPixel
# undef TestPixel
}
ATIWaitQueue(4);
outw(EXT_GE_CONFIG, ext_ge_config);
misc_options |= Test_Case[Case_Number].Miscellaneous_Options_Setting;
outw(MISC_OPTIONS, misc_options);
outw(MEM_BNDRY, mem_bndry);
outw(CLOCK_SEL, clock_sel);
ProbeWaitIdleEmpty();
return Test_Case[Case_Number].videoRamSize;
}
#endif
static void
ATIReportMemory
(
ScrnInfoPtr pScreenInfo,
ATIPtr pATI,
const char *MemoryTypeName
)
{
char Buffer[128], *Message;
Message = Buffer +
snprintf(Buffer, SizeOf(Buffer), "%d kB of %s detected",
pATI->VideoRAM, MemoryTypeName);
#ifndef AVOID_CPIO
if (pATI->depth == 1)
{
pScreenInfo->videoRam /= 4;
Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
" (using %d kB)", pScreenInfo->videoRam);
}
else
#endif
if (pATI->VideoRAM > pScreenInfo->videoRam)
{
Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
" (using %d kB)", pScreenInfo->videoRam);
}
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
}
static const int videoRamSizes[] =
{0, 256, 512, 1024, 2*1024, 4*1024, 6*1024, 8*1024, 12*1024, 16*1024, 0};
static const rgb defaultWeight = {0, 0, 0};
static const Gamma defaultGamma = {0.0, 0.0, 0.0};
static void
ATIMach64Map
(
int iScreen,
ATIPtr pATI
)
{
(void)ATIMapApertures(iScreen, pATI);
if (!pATI->pBlock[0] ||
(pATI->config_chip_id != inr(CONFIG_CHIP_ID)))
ATIUnmapApertures(iScreen, pATI);
}
static void
ATIPrintNoiseIfRequested
(
ATIPtr pATI,
CARD8 *BIOS,
unsigned int BIOSSize
)
{
if (xf86GetVerbosity() <= 3)
return;
if (BIOSSize > 0)
ATIPrintBIOS(BIOS, BIOSSize);
xf86ErrorFVerb(4, "\n On server entry:\n");
ATIPrintRegisters(pATI);
}
Bool
ATIPreInit
(
ScrnInfoPtr pScreenInfo,
int flags
)
{
# define BIOS_SIZE 0x00010000U
CARD8 BIOS[BIOS_SIZE];
# define BIOSByte(_n) ((CARD8)(BIOS[_n]))
# define BIOSWord(_n) ((CARD16)(BIOS[_n] | \
(BIOS[(_n) + 1] << 8)))
# define BIOSLong(_n) ((CARD32)(BIOS[_n] | \
(BIOS[(_n) + 1] << 8) | \
(BIOS[(_n) + 2] << 16) | \
(BIOS[(_n) + 3] << 24)))
unsigned int BIOSSize = 0;
unsigned int ROMTable = 0, ClockTable = 0, FrequencyTable = 0;
unsigned int LCDTable = 0, LCDPanelInfo = 0, VideoTable = 0;
unsigned int HardwareTable = 0;
char Buffer[128], *Message;
ATIPtr pATI;
GDevPtr pGDev;
EntityInfoPtr pEntity;
resPtr pResources;
pciVideoPtr pVideo;
DisplayModePtr pMode;
unsigned long Block0Base;
CARD32 IOValue;
int i, j, AcceleratorVideoRAM = 0, ServerVideoRAM;
int Numerator, Denominator;
int MinX, MinY;
ClockRange ATIClockRange = {NULL, 0, 80000, 0, TRUE, TRUE, 1, 1, 0};
int DefaultmaxClock = 0;
int minPitch, maxPitch = 0xFFU, maxHeight = 0;
int ApertureSize = 0x00010000U;
int ModeType = M_T_BUILTIN;
LookupModeFlags Strategy = LOOKUP_CLOSEST_CLOCK;
int DefaultDepth;
# define pATIHW (&pATI->OldHW)
#ifndef AVOID_CPIO
xf86Int10InfoPtr pInt10Info = NULL;
vbeInfoPtr pVBE;
pointer pInt10Module, pDDCModule = NULL, pVBEModule = NULL;
int VGAVideoRAM = 0;
resRange Resources[2] = {{0, 0, 0}, _END};
#endif
if (pScreenInfo->numEntities != 1)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Logic error: Number of attached entities not 1.\n");
return FALSE;
}
pATI = ATIPTR(pScreenInfo);
if (pATI->iEntity != pScreenInfo->entityList[0])
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Logic error: Entity mismatch.\n");
return FALSE;
}
pEntity = xf86GetEntityInfo(pATI->iEntity);
pGDev = pEntity->device;
pResources = pEntity->resources;
xfree(pEntity);
if (!pResources)
pResources = xf86RegisterResources(pATI->iEntity, NULL,
pATI->SharedAccelerator ? ResShared : ResExclusive);
if (pResources)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Unable to register the following bus resources:\n");
xf86PrintResList(0, pResources);
xf86FreeResList(pResources);
return FALSE;
}
ConfiguredMonitor = NULL;
(void)memset(BIOS, 0, SizeOf(BIOS));
if (!(flags & PROBE_DETECT))
{
xf86DrvMsg(pScreenInfo->scrnIndex,
pATI->Chipset ? X_CONFIG : X_DEFAULT,
"Chipset: \"%s\".\n", ATIChipsetNames[pATI->Chipset]);
switch (pATI->Chipset)
{
#ifndef AVOID_CPIO
case ATI_CHIPSET_IBMVGA:
if (pATI->Adapter == ATI_ADAPTER_VGA)
break;
case ATI_CHIPSET_VGAWONDER:
pATI->Chipset = ATI_CHIPSET_ATIVGA;
break;
case ATI_CHIPSET_IBM8514:
if (pATI->Adapter == ATI_ADAPTER_8514A)
break;
case ATI_CHIPSET_MACH8:
case ATI_CHIPSET_MACH32:
#endif
case ATI_CHIPSET_MACH64:
case ATI_CHIPSET_RAGE128:
case ATI_CHIPSET_RADEON:
pATI->Chipset = ATI_CHIPSET_ATI;
break;
default:
break;
}
pScreenInfo->monitor = pScreenInfo->confScreen->monitor;
if ((pATI->Chipset != ATI_CHIPSET_ATI) ||
(pATI->Chip < ATI_CHIP_264CT))
{
i = NoDepth24Support;
DefaultDepth = 8;
}
else
{
i = Support24bppFb | Support32bppFb;
DefaultDepth = 0;
}
if (!xf86SetDepthBpp(pScreenInfo, DefaultDepth, 0, 0, i))
return FALSE;
for (j = 0; ; j++)
{
static const CARD8 AllowedDepthBpp[][2] =
{
#ifndef AVOID_CPIO
{ 1, 1},
{ 4, 4},
{ 4, 8},
#endif
{ 8, 8},
{15, 16},
{16, 16},
{24, 24},
{24, 32}
};
if (j < NumberOf(AllowedDepthBpp))
{
if (pScreenInfo->depth > AllowedDepthBpp[j][0])
continue;
if (pScreenInfo->depth == AllowedDepthBpp[j][0])
{
if (pScreenInfo->bitsPerPixel > AllowedDepthBpp[j][1])
continue;
if (pScreenInfo->bitsPerPixel == AllowedDepthBpp[j][1])
break;
}
}
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Driver does not support depth %d at fbbpp %d.\n",
pScreenInfo->depth, pScreenInfo->bitsPerPixel);
return FALSE;
}
xf86PrintDepthBpp(pScreenInfo);
if ((i == NoDepth24Support) && (pScreenInfo->depth > 8))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Depth %d is not supported through this adapter.\n",
pScreenInfo->depth);
return FALSE;
}
ATIProcessOptions(pScreenInfo, pATI);
}
#ifdef AVOID_CPIO
else
{
return TRUE;
}
#else
if (!(pInt10Module = ATILoadModule(pScreenInfo, "int10", ATIint10Symbols)))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to load int10 module.\n");
}
else if (!(pInt10Info = xf86InitInt10(pATI->iEntity)))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to initialise int10 interface.\n");
}
else
{
if (!(pDDCModule = ATILoadModule(pScreenInfo, "ddc", ATIddcSymbols)))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to load ddc module.\n");
}
else
if (!(pVBEModule = ATILoadModule(pScreenInfo, "vbe", ATIvbeSymbols)))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to load vbe module.\n");
}
else
{
if ((pVBE = VBEInit(pInt10Info, pATI->iEntity)))
{
ConfiguredMonitor = vbeDoEDID(pVBE, pDDCModule);
vbeFree(pVBE);
}
xf86UnloadSubModule(pVBEModule);
}
if (!(flags & PROBE_DETECT))
{
CARD8 *pBIOS = xf86int10Addr(pInt10Info, pInt10Info->BIOSseg << 4);
if ((pBIOS[0] != 0x55U) || (pBIOS[1] != 0xAAU) || !pBIOS[2])
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to correctly retrieve adapter BIOS.\n");
}
else
{
BIOSSize = pBIOS[2] << 9;
if (BIOSSize > BIOS_SIZE)
BIOSSize = BIOS_SIZE;
(void)memcpy(BIOS, pBIOS, BIOSSize);
}
}
}
xf86FreeInt10(pInt10Info);
xf86UnloadSubModule(pInt10Module);
if (flags & PROBE_DETECT)
{
xf86UnloadSubModule(pDDCModule);
return TRUE;
}
if (ConfiguredMonitor)
{
xf86PrintEDID(ConfiguredMonitor);
xf86SetDDCproperties(pScreenInfo, ConfiguredMonitor);
}
xf86UnloadSubModule(pDDCModule);
#endif
pATI->Block0Base = 0;
if ((pVideo = pATI->PCIInfo))
{
if (pATI->CPIODecoding == BLOCK_IO)
pATI->CPIOBase = pVideo->ioBase[1];
if ((pATI->Block0Base = pVideo->memBase[2]))
{
if (pATI->Block0Base >= (CARD32)(-1 << pVideo->size[2]))
pATI->Block0Base = 0;
else
pATI->Block0Base += 0x0400U;
}
}
#ifdef AVOID_CPIO
pScreenInfo->racMemFlags =
RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
#else
pScreenInfo->racIoFlags =
RAC_FB | RAC_COLORMAP | RAC_VIEWPORT | RAC_CURSOR;
pScreenInfo->racMemFlags = RAC_FB | RAC_CURSOR;
#endif
if (pGDev->chipID >= 0)
{
ATIChipType Chip;
Chip = ATIChipID(pGDev->chipID,
(pGDev->chipRev < 0) ? pATI->ChipRev : pGDev->chipRev);
if (Chip != pATI->Chip)
{
pATI->Chip = Chip;
pATI->ChipType = pGDev->chipID;
if (pGDev->chipRev < 0)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
"Driver messages reflect ChipID 0x%04X override.\n",
pATI->ChipType);
}
else
{
pATI->ChipRev = pGDev->chipRev;
pATI->ChipVersion = GetBits(pATI->ChipRev,
GetBits(CFG_CHIP_VERSION, CFG_CHIP_REV));
pATI->ChipFoundry = GetBits(pATI->ChipRev,
GetBits(CFG_CHIP_FOUNDRY, CFG_CHIP_REV));
pATI->ChipRevision = GetBits(pATI->ChipRev,
GetBits(CFG_CHIP_REVISION, CFG_CHIP_REV));
xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
"Driver messages reflect ChipID 0x%04X and ChipRev 0x%02X"
" overrides.\n", pATI->ChipType, pATI->ChipRev);
}
}
}
pATI->DAC = ATI_DAC_GENERIC;
#ifndef AVOID_CPIO
pATI->NewHW.SetBank = ATIx8800SetBank;
pATI->BankInfo.SetSourceBank = ATIx8800SetRead;
pATI->BankInfo.SetDestinationBank = ATIx8800SetWrite;
pATI->BankInfo.SetSourceAndDestinationBanks = ATIx8800SetReadWrite;
pATI->BankInfo.BankSize = 0x00010000U;
#endif
pATI->LCDPanelID = -1;
pATI->nFIFOEntries = 16;
pATI->Audio = ATI_AUDIO_NONE;
switch (pATI->Adapter)
{
#ifndef AVOID_CPIO
case ATI_ADAPTER_NONE:
case ATI_ADAPTER_EGA:
case ATI_ADAPTER_EGA_PLUS:
case ATI_ADAPTER_VGA:
case ATI_ADAPTER_BASIC:
pATI->NewHW.SetBank = (ATIBankProcPtr)NoopDDA;
pATI->BankInfo.SetSourceBank =
pATI->BankInfo.SetDestinationBank =
pATI->BankInfo.SetSourceAndDestinationBanks =
(miBankProcPtr)NoopDDA;
break;
case ATI_ADAPTER_V3:
pATI->NewHW.SetBank = ATIV3SetBank;
pATI->BankInfo.SetSourceBank = ATIV3SetRead;
pATI->BankInfo.SetDestinationBank = ATIV3SetWrite;
pATI->BankInfo.SetSourceAndDestinationBanks = ATIV3SetReadWrite;
break;
case ATI_ADAPTER_V4:
case ATI_ADAPTER_V5:
pATI->NewHW.SetBank = ATIV4V5SetBank;
pATI->BankInfo.SetSourceBank = ATIV4V5SetRead;
pATI->BankInfo.SetDestinationBank = ATIV4V5SetWrite;
pATI->BankInfo.SetSourceAndDestinationBanks = ATIV4V5SetReadWrite;
break;
case ATI_ADAPTER_XL:
pATI->DAC = ATI_DAC_SC11483;
break;
case ATI_ADAPTER_8514A:
pATI->VideoRAM =
videoRamSizes[GetBits(inw(SUBSYS_STAT), _8PLANE) + 2];
break;
case ATI_ADAPTER_MACH8:
pATI->VideoRAM =
videoRamSizes[GetBits(inw(CONFIG_STATUS_1), MEM_INSTALLED) + 2];
break;
case ATI_ADAPTER_MACH32:
IOValue = inw(CONFIG_STATUS_1);
pATI->DAC = ATI_DAC(GetBits(IOValue, DACTYPE), 0);
pATI->MemoryType = GetBits(IOValue, MEM_TYPE);
IOValue = inw(MISC_OPTIONS);
pATI->VideoRAM =
videoRamSizes[GetBits(IOValue, MEM_SIZE_ALIAS) + 2];
if ((pATI->Chip == ATI_CHIP_68800_6) && (pATI->VideoRAM == 1024))
pATI->VideoRAM = ATIMach32videoRam();
break;
#endif
case ATI_ADAPTER_MACH64:
do
{
if (!(Block0Base = pATI->Block0Base))
{
if (pVideo)
{
if ((pATI->Block0Base = pVideo->memBase[0]))
{
pATI->Block0Base += 0x007FFC00U;
ATIMach64Map(pScreenInfo->scrnIndex, pATI);
if (pATI->pBlock[0])
break;
pATI->Block0Base -= 0x00400000U;
ATIMach64Map(pScreenInfo->scrnIndex, pATI);
if (pATI->pBlock[0])
break;
}
}
pATI->Block0Base = 0x000BFC00U;
}
ATIMach64Map(pScreenInfo->scrnIndex, pATI);
} while (0);
pATI->Block0Base = Block0Base;
#ifdef AVOID_CPIO
if (!pATI->pBlock[0])
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Unable to mmap() adapter registers.\n");
return FALSE;
}
#endif
pATIHW->crtc_gen_cntl = inr(CRTC_GEN_CNTL);
if (!(pATIHW->crtc_gen_cntl & CRTC_EN) &&
(pATI->Chip >= ATI_CHIP_264CT))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Adapter has not been initialised.\n");
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
#ifdef AVOID_CPIO
if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Adapters found to be in VGA mode on server entry are not"
" supported by the MMIO-only version of this driver.\n");
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
#endif
pATIHW->mem_cntl = inr(MEM_CNTL);
if (pATI->Chip < ATI_CHIP_264VTB)
{
pATI->VideoRAM =
videoRamSizes[GetBits(pATIHW->mem_cntl, CTL_MEM_SIZE) + 2];
}
else
{
pATI->nFIFOEntries =
(unsigned int)(-1) >> 1;
IOValue = GetBits(pATIHW->mem_cntl, CTL_MEM_SIZEB);
if (IOValue < 8)
pATI->VideoRAM = (IOValue + 1) * 512;
else if (IOValue < 12)
pATI->VideoRAM = (IOValue - 3) * 1024;
else
pATI->VideoRAM = (IOValue - 7) * 2048;
}
pATI->DAC = GetBits(inr(DAC_CNTL), DAC_TYPE);
IOValue = inr(CONFIG_STATUS64_0);
if (pATI->Chip >= ATI_CHIP_264CT)
{
pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE_T);
if (pATI->Chip == ATI_CHIP_264LT)
{
pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
pATIHW->horz_stretching = inr(HORZ_STRETCHING);
pATIHW->vert_stretching = inr(VERT_STRETCHING);
pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
}
else if ((pATI->Chip == ATI_CHIP_264LTPRO) ||
(pATI->Chip == ATI_CHIP_264XL) ||
(pATI->Chip == ATI_CHIP_MOBILITY))
{
pATI->LCDPanelID = GetBits(IOValue, CFG_PANEL_ID);
pATIHW->lcd_index = inr(LCD_INDEX);
pATIHW->horz_stretching =
ATIMach64GetLCDReg(LCD_HORZ_STRETCHING);
pATI->LCDHorizontal =
GetBits(pATIHW->horz_stretching, HORZ_PANEL_SIZE);
if (pATI->LCDHorizontal)
{
if (pATI->LCDHorizontal == MaxBits(HORZ_PANEL_SIZE))
pATI->LCDHorizontal = 0;
else
pATI->LCDHorizontal =
(pATI->LCDHorizontal + 1) << 3;
}
pATIHW->ext_vert_stretch =
ATIMach64GetLCDReg(LCD_EXT_VERT_STRETCH);
pATI->LCDVertical =
GetBits(pATIHW->ext_vert_stretch, VERT_PANEL_SIZE);
if (pATI->LCDVertical)
{
if (pATI->LCDVertical == MaxBits(VERT_PANEL_SIZE))
pATI->LCDVertical = 0;
else
pATI->LCDVertical++;
}
pATIHW->vert_stretching =
ATIMach64GetLCDReg(LCD_VERT_STRETCHING);
pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
outr(LCD_INDEX, pATIHW->lcd_index);
}
if ((pATI->LCDPanelID >= 0) &&
!(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
!(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
!(pATIHW->lcd_gen_ctrl & LCD_ON))
{
if ((pATI->Chip >= ATI_CHIP_264XL) &&
(!pATI->LCDHorizontal || !pATI->LCDVertical))
pATI->LCDPanelID = -1;
else
pATI->OptionPanelDisplay = FALSE;
}
}
else
{
pATI->MemoryType = GetBits(IOValue, CFG_MEM_TYPE);
pATI->DAC = ATI_DAC(pATI->DAC,
GetBits(inr(SCRATCH_REG1), BIOS_INIT_DAC_SUBTYPE));
}
if (pATI->DAC < ATI_DAC_ATI68875)
pATI->DAC += ATI_DAC_INTERNAL;
break;
default:
break;
}
#ifndef AVOID_CPIO
if (pATI->Chip >= ATI_CHIP_88800GXC)
#endif
{
CARD16 ClockDac;
pATI->ClockDescriptor = ATIClockDescriptors[ATI_CLOCK_FIXED];
pATI->ClockNumberToProgramme = -1;
ROMTable = BIOSWord(0x48U);
if ((ROMTable < 0x0002U) ||
(BIOSWord(ROMTable - 0x02U) < 0x0012U) ||
((ROMTable + BIOSWord(ROMTable - 0x02U)) > BIOSSize))
ROMTable = 0;
if (ROMTable > 0)
{
ClockTable = BIOSWord(ROMTable + 0x10U);
if ((ClockTable + 0x20U) > BIOSSize)
ClockTable = 0;
if (BIOSWord(ROMTable - 0x02U) >= 0x0048U)
{
VideoTable = BIOSWord(ROMTable + 0x46U);
if ((VideoTable < 0x08U) ||
(BIOSByte(VideoTable - 0x01U) < 0x08U) ||
(BIOSByte(VideoTable - 0x02U) > 0x01U) ||
((VideoTable + BIOSByte(VideoTable - 0x01U)) > BIOSSize))
VideoTable = 0;
}
if (BIOSWord(ROMTable - 0x02U) >= 0x004AU)
{
HardwareTable = BIOSWord(ROMTable + 0x48U);
if (((HardwareTable + 0x08U) <= BIOSSize) &&
!memcmp(BIOS + HardwareTable, "$ATI", 4))
pATI->I2CType = BIOSByte(HardwareTable + 0x06U) & 0x0FU;
else
HardwareTable = 0;
}
}
if (ClockTable > 0)
{
FrequencyTable = BIOSWord(ClockTable - 0x02U);
if ((FrequencyTable > 0) &&
((FrequencyTable + 0x20U) <= BIOSSize))
{
for (i = 0; i < 16; i++)
{
pATI->BIOSClocks[i] = BIOSWord(FrequencyTable);
FrequencyTable += 2;
}
}
pATI->ProgrammableClock = BIOSByte(ClockTable);
pATI->ClockNumberToProgramme = BIOSByte(ClockTable + 0x06U);
switch (BIOSWord(ClockTable + 0x08U) / 10)
{
case 143:
pATI->ReferenceNumerator = 157500;
pATI->ReferenceDenominator = 11;
break;
case 286:
pATI->ReferenceNumerator = 315000;
pATI->ReferenceDenominator = 11;
break;
default:
pATI->ReferenceNumerator =
BIOSWord(ClockTable + 0x08U) * 10;
pATI->ReferenceDenominator = 1;
break;
}
}
else
{
if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
{
pATI->ProgrammableClock = ATI_CLOCK_INTERNAL;
}
else switch (pATI->DAC)
{
case ATI_DAC_STG1703:
pATI->ProgrammableClock = ATI_CLOCK_STG1703;
break;
case ATI_DAC_CH8398:
pATI->ProgrammableClock = ATI_CLOCK_CH8398;
break;
case ATI_DAC_ATT20C408:
pATI->ProgrammableClock = ATI_CLOCK_ATT20C408;
break;
case ATI_DAC_IBMRGB514:
pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
break;
default:
pATI->ProgrammableClock = ATI_CLOCK_ICS2595;
break;
}
pATI->ClockNumberToProgramme = 3;
}
if ((pATI->ProgrammableClock > ATI_CLOCK_FIXED) &&
(pATI->ProgrammableClock < ATI_CLOCK_MAX))
{
if ((pATI->ProgrammableClock == ATI_CLOCK_ICS2595) &&
(pATI->DAC == ATI_DAC_IBMRGB514) &&
(pScreenInfo->depth >= 8) &&
(pATI->Chipset == ATI_CHIPSET_ATI))
pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
pATI->ClockDescriptor =
ATIClockDescriptors[pATI->ProgrammableClock];
}
ClockDac = pATI->DAC;
switch (pATI->ProgrammableClock)
{
case ATI_CLOCK_ICS2595:
if (ClockTable > 0)
pATI->ClockDescriptor.MinM =
pATI->ClockDescriptor.MaxM =
BIOSWord(ClockTable + 0x0AU);
else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-0"))
pATI->ClockDescriptor.MinM =
pATI->ClockDescriptor.MaxM = 43;
else if (!xf86NameCmp(pGDev->clockchip, "ATI 18818-1"))
pATI->ClockDescriptor.MinM =
pATI->ClockDescriptor.MaxM = 46;
else
pATI->ProgrammableClock = ATI_CLOCK_UNKNOWN;
break;
case ATI_CLOCK_STG1703:
ClockDac = ATI_DAC_STG1703;
break;
case ATI_CLOCK_CH8398:
ClockDac = ATI_DAC_CH8398;
break;
case ATI_CLOCK_INTERNAL:
pATI->ClockDescriptor.MinM = pATI->ClockDescriptor.MaxM =
ATIMach64GetPLLReg(PLL_REF_DIV);
if ((pATI->DAC & ~0x0FU) != ATI_DAC_INTERNAL)
ClockDac = ATI_DAC_INTERNAL;
break;
case ATI_CLOCK_ATT20C408:
ClockDac = ATI_DAC_ATT20C408;
break;
case ATI_CLOCK_IBMRGB514:
ClockDac = ATI_DAC_IBMRGB514;
pATI->ClockNumberToProgramme = 7;
break;
default:
break;
}
if (pATI->DAC != ClockDac)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Mach64 RAMDAC probe discrepancy detected:\n"
" DAC=0x%02X; ClockDac=0x%02X.\n",
pATI->DAC, ClockDac);
if (pATI->DAC == ATI_DAC_IBMRGB514)
{
pATI->ProgrammableClock = ATI_CLOCK_IBMRGB514;
pATI->ClockDescriptor =
ATIClockDescriptors[ATI_CLOCK_IBMRGB514];
pATI->ClockNumberToProgramme = 7;
}
else
{
pATI->DAC = ClockDac;
}
}
if (VideoTable > 0)
{
switch (BIOSByte(VideoTable - 0x02U))
{
case 0x00U:
pATI->Tuner = BIOSByte(VideoTable) & 0x1FU;
switch (pATI->Chip)
{
case ATI_CHIP_264LTPRO:
case ATI_CHIP_MOBILITY:
pATI->Decoder =
BIOSByte(VideoTable + 0x01U) & 0x07U;
pATI->Audio =
BIOSByte(VideoTable + 0x02U) & 0x0FU;
break;
default:
pATI->Decoder =
BIOSByte(VideoTable + 0x02U) & 0x07U;
pATI->Audio =
BIOSByte(VideoTable + 0x03U) & 0x0FU;
break;
}
break;
case 0x01U:
pATI->Tuner = BIOSByte(VideoTable) & 0x1FU;
pATI->Audio = BIOSByte(VideoTable + 0x01U) & 0x0FU;
pATI->Decoder = BIOSByte(VideoTable + 0x05U) & 0x0FU;
break;
default:
break;
}
}
if (pATI->LCDPanelID >= 0)
{
LCDTable = BIOSWord(0x78U);
if ((LCDTable + BIOSByte(LCDTable + 5)) > BIOSSize)
LCDTable = 0;
if (LCDTable > 0)
{
LCDPanelInfo = BIOSWord(LCDTable + 0x0AU);
if (((LCDPanelInfo + 0x1DU) > BIOSSize) ||
((BIOSByte(LCDPanelInfo) != pATI->LCDPanelID) &&
(pATI->LCDPanelID || (BIOSByte(LCDPanelInfo) > 0x1FU) ||
(pATI->Chip <= ATI_CHIP_264LTPRO))))
LCDPanelInfo = 0;
}
if (!LCDPanelInfo)
{
for (i = 0; i <= (int)(BIOSSize - 0x1DU); i++)
{
if ((BIOSByte(i) != pATI->LCDPanelID) &&
(pATI->LCDPanelID || (BIOSByte(i) > 0x1FU) ||
(pATI->Chip <= ATI_CHIP_264LTPRO)))
continue;
for (j = 0; j < 24; j++)
{
if ((CARD8)(BIOSByte(i + j + 1) - 0x20U) > 0x5FU)
{
i += j;
goto NextBIOSByte;
}
}
if (pATI->LCDHorizontal &&
(pATI->LCDHorizontal != BIOSWord(i + 0x19U)))
continue;
if (pATI->LCDVertical &&
(pATI->LCDVertical != BIOSWord(i + 0x1BU)))
continue;
if (LCDPanelInfo)
{
if ((BIOSByte(LCDPanelInfo + 0x19U) ==
BIOSByte(i + 0x19U)) &&
(BIOSByte(LCDPanelInfo + 0x1AU) ==
BIOSByte(i + 0x1AU)) &&
(BIOSByte(LCDPanelInfo + 0x1BU) ==
BIOSByte(i + 0x1BU)) &&
(BIOSByte(LCDPanelInfo + 0x1CU) ==
BIOSByte(i + 0x1CU)))
continue;
LCDPanelInfo = 0;
break;
}
LCDPanelInfo = i;
NextBIOSByte: ;
}
}
if (LCDPanelInfo > 0)
{
pATI->LCDPanelID = BIOSByte(LCDPanelInfo);
pATI->LCDHorizontal = BIOSWord(LCDPanelInfo + 0x19U);
pATI->LCDVertical = BIOSWord(LCDPanelInfo + 0x1BU);
}
}
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
"BIOS Data: BIOSSize=0x%04X, ROMTable=0x%04X.\n",
BIOSSize, ROMTable);
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
"BIOS Data: ClockTable=0x%04X, FrequencyTable=0x%04X.\n",
ClockTable, FrequencyTable);
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
"BIOS Data: LCDTable=0x%04X, LCDPanelInfo=0x%04X.\n",
LCDTable, LCDPanelInfo);
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
"BIOS Data: VideoTable=0x%04X, HardwareTable=0x%04X.\n",
VideoTable, HardwareTable);
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_INFO, 3,
"BIOS Data: I2CType=0x%02X, Tuner=0x%02X, Decoder=0x%02X,"
" Audio=0x%02X.\n",
pATI->I2CType, pATI->Tuner, pATI->Decoder, pATI->Audio);
}
ATIUnlock(pATI);
#ifndef AVOID_CPIO
if ((pATI->Chip >= ATI_CHIP_28800_4) && (pATI->Chip <= ATI_CHIP_28800_6))
{
IOValue = GetBits(ATIGetExtReg(0xAAU), 0x0FU) +
(ATI_CHIP_28800_4 - 4);
if ((IOValue <= ATI_CHIP_28800_6) && (IOValue > pATI->Chip))
pATI->Chip = IOValue;
}
#endif
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%s graphics controller detected.\n", ATIChipNames[pATI->Chip]);
#ifndef AVOID_CPIO
if ((pATI->Chip >= ATI_CHIP_68800) && (pATI->Chip != ATI_CHIP_68800_3))
#endif
{
Message = Buffer + snprintf(Buffer, SizeOf(Buffer), "Chip type %04X",
pATI->ChipType);
if (!(pATI->ChipType & ~(CHIP_CODE_0 | CHIP_CODE_1)))
Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
" (%c%c)",
GetBits(pATI->ChipType, CHIP_CODE_1) + 0x41U,
GetBits(pATI->ChipType, CHIP_CODE_0) + 0x41U);
else if ((pATI->ChipType & 0x4040U) == 0x4040U)
Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
" \"%c%c\"",
GetByte(pATI->ChipType, 1), GetByte(pATI->ChipType, 0));
if ((pATI->Chip >= ATI_CHIP_264CT) && (pATI->Chip != ATI_CHIP_Mach64))
Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
", version %d, foundry %s",
pATI->ChipVersion, ATIFoundryNames[pATI->ChipFoundry]);
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%s, class %d, revision 0x%02X.\n",
Buffer, pATI->ChipClass, pATI->ChipRevision);
}
#ifndef AVOID_CPIO
if (pATI->Adapter >= ATI_ADAPTER_MACH8)
#endif
{
Message = Buffer + snprintf(Buffer, SizeOf(Buffer),
"%s bus interface detected", ATIBusNames[pATI->BusType]);
#ifndef AVOID_CPIO
if (pATI->Adapter >= ATI_ADAPTER_MACH64)
{
Message += snprintf(Message, Buffer + SizeOf(Buffer) - Message,
"; %s I/O base is 0x%04lX",
(pATI->CPIODecoding == SPARSE_IO) ? "sparse" : "block",
pATI->CPIOBase);
}
#endif
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED, "%s.\n", Buffer);
}
#ifndef AVOID_CPIO
if (pATI->CPIO_VGAWonder)
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"VGA Wonder registers at I/O port 0x%04lX.\n",
pATI->CPIO_VGAWonder);
if (pATI->Coprocessor != ATI_CHIP_NONE)
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%s graphics accelerator detected,\n with %d kB of coprocessor"
" memory.\n",
ATIChipNames[pATI->Coprocessor], pATI->VideoRAM);
#endif
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%s adapter detected.\n", ATIAdapterNames[pATI->Adapter]);
if (pATI->Chip >= ATI_CHIP_264GT)
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"For information on using the multimedia capabilities\n of this"
" adapter, please see http://gatos.sf.net.\n");
if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"Internal RAMDAC (subtype %d) detected.\n", pATI->DAC & 0x0FU);
}
else
{
const SymTabRec *DAC;
for (DAC = ATIDACDescriptors; ; DAC++)
{
if (pATI->DAC == DAC->token)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%s RAMDAC detected.\n", DAC->name);
break;
}
if (pATI->DAC < DAC->token)
{
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_WARNING, 0,
"Unknown RAMDAC type 0x%02X detected.\n", pATI->DAC);
break;
}
}
}
#ifdef AVOID_CPIO
if (!xf86LinearVidMem())
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"A linear aperture is not available.\n");
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
#endif
if (pATI->Chip < ATI_CHIP_264CT)
pScreenInfo->rgbBits = 6;
else
pScreenInfo->rgbBits = 8;
pATI->rgbBits = pScreenInfo->rgbBits;
if (!xf86SetWeight(pScreenInfo, defaultWeight, defaultWeight))
{
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
if ((pScreenInfo->depth > 8) &&
((pScreenInfo->weight.red != pScreenInfo->weight.blue) ||
(pScreenInfo->weight.red != (CARD32)(pScreenInfo->depth / 3)) ||
((CARD32)pScreenInfo->depth != (pScreenInfo->weight.red +
pScreenInfo->weight.green +
pScreenInfo->weight.blue))))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Driver does not support weight %d%d%d for depth %d.\n",
(int)pScreenInfo->weight.red, (int)pScreenInfo->weight.green,
(int)pScreenInfo->weight.blue, pScreenInfo->depth);
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
if (!xf86SetDefaultVisual(pScreenInfo, -1))
{
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
if ((pScreenInfo->depth > 8) &&
(((pScreenInfo->defaultVisual | DynamicClass) != DirectColor) ||
((pScreenInfo->defaultVisual == DirectColor) &&
(pATI->DAC == ATI_DAC_INTERNAL))))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Driver does not support default visual %s for depth %d.\n",
xf86GetVisualName(pScreenInfo->defaultVisual),
pScreenInfo->depth);
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
#ifndef AVOID_CPIO
if (pScreenInfo->depth > 1)
#endif
{
if (!xf86SetGamma(pScreenInfo, defaultGamma))
{
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
}
pATI->depth = pScreenInfo->depth;
pATI->bitsPerPixel = pScreenInfo->bitsPerPixel;
pATI->weight = pScreenInfo->weight;
pATI->XModifier = pATI->bitsPerPixel / UnitOf(pATI->bitsPerPixel);
#ifndef AVOID_CPIO
if ((pATI->Chip >= ATI_CHIP_88800GXC) &&
(pATI->depth >= 8) &&
(pATI->Chipset == ATI_CHIPSET_ATI))
#endif
{
pATI->NewHW.crtc = ATI_CRTC_MACH64;
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using Mach64 accelerator CRTC.\n");
#ifndef AVOID_CPIO
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
{
pResources =
xf86SetOperatingState(resVgaIo, pATI->iEntity, ResUnusedOpr);
if (pResources)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Logic error setting operating state for VGA I/O.\n");
xf86FreeResList(pResources);
}
if (pATI->CPIO_VGAWonder)
{
pResources = xf86SetOperatingState(pATI->VGAWonderResources,
pATI->iEntity, ResUnusedOpr);
if (pResources)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Logic error setting operating state for"
" VGAWonder I/O.\n");
xf86FreeResList(pResources);
}
}
}
#endif
}
#ifndef AVOID_CPIO
else
{
pATI->NewHW.crtc = ATI_CRTC_VGA;
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using VGA CRTC.\n");
}
if ((pATI->NewHW.crtc == ATI_CRTC_VGA) || !pATI->OptionLinear)
{
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"VGA is not available through this adapter.\n");
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
if (pATI->Coprocessor != ATI_CHIP_NONE)
{
pATI->Adapter = pATI->VGAAdapter;
pATI->VideoRAM = 0;
}
}
#endif
if (pATI->LCDPanelID >= 0)
{
if (!pATI->OptionPanelDisplay)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_CONFIG,
"Using CRT interface and disabling digital flat panel.\n");
}
else
{
unsigned HDisplay, VDisplay;
CARD8 ClockMask, PostMask;
if (pATI->Chip == ATI_CHIP_264LT)
{
pATIHW->lcd_gen_ctrl = inr(LCD_GEN_CTRL);
if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN)
outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN);
}
else
{
pATIHW->lcd_index = inr(LCD_INDEX);
pATIHW->config_panel = ATIMach64GetLCDReg(LCD_CONFIG_PANEL);
pATIHW->lcd_gen_ctrl = ATIMach64GetLCDReg(LCD_GEN_CNTL);
if (pATIHW->lcd_gen_ctrl & SHADOW_RW_EN)
ATIMach64PutLCDReg(LCD_GEN_CNTL,
pATIHW->lcd_gen_ctrl & ~SHADOW_RW_EN);
}
#ifndef AVOID_CPIO
if (!(pATIHW->crtc_gen_cntl & CRTC_EXT_DISP_EN))
{
unsigned HBlankStart, HSyncStart, HSyncEnd, HBlankEnd, HTotal;
unsigned VBlankStart, VSyncStart, VSyncEnd, VBlankEnd, VTotal;
pATIHW->clock = (inb(R_GENMO) & 0x0CU) >> 2;
pATIHW->crt[2] = GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
pATIHW->crt[3] = GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
pATIHW->crt[5] = GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
pATIHW->crt[7] = GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
pATIHW->crt[9] = GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
pATIHW->crt[21] = GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
pATIHW->crt[22] = GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
if (pATI->Chip == ATI_CHIP_264LT)
outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
else
ATIMach64PutLCDReg(LCD_GEN_CNTL,
pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
pATIHW->shadow_vga[2] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x02U);
pATIHW->shadow_vga[3] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x03U);
pATIHW->shadow_vga[5] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x05U);
pATIHW->shadow_vga[7] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x07U);
pATIHW->shadow_vga[9] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x09U);
pATIHW->shadow_vga[21] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x15U);
pATIHW->shadow_vga[22] =
GetReg(CRTX(pATI->CPIO_VGABase), 0x16U);
pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
if (((pATIHW->crtc_h_sync_strt_wid ^
pATIHW->shadow_h_sync_strt_wid) &
(CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI |
CRTC_H_SYNC_WID)))
{
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0,
"Invalid horizontal sync pulse timing detected in mode"
" on server entry.\n");
pATI->OptionLCDSync = TRUE;
ModeType = 0;
}
if (pATIHW->lcd_gen_ctrl & SHADOW_EN)
{
pATIHW->crt[2] = pATIHW->shadow_vga[2];
pATIHW->crt[3] = pATIHW->shadow_vga[3];
pATIHW->crt[5] = pATIHW->shadow_vga[5];
if ((pATI->Chip < ATI_CHIP_264LTPRO) ||
!(pATIHW->config_panel & DONT_SHADOW_HEND))
{
pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP;
pATIHW->crtc_h_total_disp |=
pATIHW->shadow_h_total_disp & CRTC_H_DISP;
}
pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL;
pATIHW->crtc_h_total_disp |=
pATIHW->shadow_h_total_disp & CRTC_H_TOTAL;
pATIHW->crtc_h_sync_strt_wid =
pATIHW->shadow_h_sync_strt_wid;
if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND)
{
pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP;
pATIHW->crtc_v_total_disp |=
pATIHW->shadow_v_total_disp & CRTC_V_DISP;
}
if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
{
pATIHW->crt[7] = pATIHW->shadow_vga[7];
pATIHW->crt[9] = pATIHW->shadow_vga[9];
pATIHW->crt[21] = pATIHW->shadow_vga[21];
pATIHW->crt[22] = pATIHW->shadow_vga[22];
pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL;
pATIHW->crtc_v_total_disp |=
pATIHW->shadow_v_total_disp & CRTC_V_TOTAL;
}
}
if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
pATIHW->crtc_v_sync_strt_wid =
pATIHW->shadow_v_sync_strt_wid;
HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP);
HSyncStart =
(GetBits(pATIHW->crtc_h_sync_strt_wid,
CRTC_H_SYNC_STRT_HI) *
(MaxBits(CRTC_H_SYNC_STRT) + 1)) |
GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT);
HSyncEnd = (HSyncStart & ~MaxBits(CRTC_H_SYNC_WID)) |
GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
if (HSyncStart >= HSyncEnd)
HSyncEnd += MaxBits(CRTC_H_SYNC_WID) + 1;
HTotal = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL);
HBlankStart = (HDisplay & ~0xFFU) | pATIHW->crt[2];
if (HDisplay > HBlankStart)
HBlankStart += 0x0100U;
HBlankEnd = (HSyncEnd & ~0x3FU) |
((pATIHW->crt[5] >> 2) & 0x20U) |
(pATIHW->crt[3] & 0x1FU);
if (HSyncEnd > (HBlankEnd + 1))
HBlankEnd += 0x40U;
VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP);
VSyncStart =
GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT);
VSyncEnd = (VSyncStart & ~MaxBits(CRTC_V_SYNC_WID)) |
GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID);
if (VSyncStart > VSyncEnd)
VSyncEnd += MaxBits(CRTC_V_SYNC_WID) + 1;
VTotal = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL);
VBlankStart = (VDisplay & ~0x03FFU) |
((pATIHW->crt[9] << 4) & 0x0200U) |
((pATIHW->crt[7] << 5) & 0x0100U) | pATIHW->crt[21];
if (VDisplay > VBlankStart)
VBlankStart += 0x0400U;
VBlankEnd = (VSyncEnd & ~0x00FFU) | pATIHW->crt[22];
if (VSyncEnd > (VBlankEnd + 1))
VBlankEnd += 0x0100U;
pATI->LCDHBlankWidth = HBlankEnd - HBlankStart;
pATI->LCDHSyncStart = HSyncStart - HBlankStart - 1;
pATI->LCDHSyncWidth = HSyncEnd - HSyncStart;
pATI->LCDVBlankWidth = VBlankEnd - VBlankStart;
pATI->LCDVSyncStart = VSyncStart - VBlankStart - 1;
pATI->LCDVSyncWidth = VSyncEnd - VSyncStart;
HDisplay = HTotal + 5 - pATI->LCDHBlankWidth;
VDisplay = VTotal + 2 - pATI->LCDVBlankWidth;
}
else
#endif
{
pATIHW->clock = inr(CLOCK_CNTL) & 0x03U;
pATIHW->crtc_h_total_disp = inr(CRTC_H_TOTAL_DISP);
pATIHW->crtc_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
pATIHW->crtc_v_total_disp = inr(CRTC_V_TOTAL_DISP);
pATIHW->crtc_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
pATIHW->ovr_wid_left_right = inr(OVR_WID_LEFT_RIGHT);
pATIHW->ovr_wid_top_bottom = inr(OVR_WID_TOP_BOTTOM);
if (pATI->Chip == ATI_CHIP_264LT)
outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
else
ATIMach64PutLCDReg(LCD_GEN_CNTL,
pATIHW->lcd_gen_ctrl | SHADOW_RW_EN);
pATIHW->shadow_h_total_disp = inr(CRTC_H_TOTAL_DISP);
pATIHW->shadow_h_sync_strt_wid = inr(CRTC_H_SYNC_STRT_WID);
pATIHW->shadow_v_total_disp = inr(CRTC_V_TOTAL_DISP);
pATIHW->shadow_v_sync_strt_wid = inr(CRTC_V_SYNC_STRT_WID);
if (((pATIHW->crtc_h_sync_strt_wid ^
pATIHW->shadow_h_sync_strt_wid) &
(CRTC_H_SYNC_STRT | CRTC_H_SYNC_STRT_HI |
CRTC_H_SYNC_WID)))
{
xf86DrvMsgVerb(pScreenInfo->scrnIndex, X_NOTICE, 0,
"Invalid horizontal sync pulse timing detected in mode"
" on server entry.\n");
pATI->OptionLCDSync = TRUE;
ModeType = 0;
}
if (pATIHW->lcd_gen_ctrl & SHADOW_EN)
{
if ((pATI->Chip < ATI_CHIP_264LTPRO) ||
!(pATIHW->config_panel & DONT_SHADOW_HEND))
{
pATIHW->crtc_h_total_disp &= ~CRTC_H_DISP;
pATIHW->crtc_h_total_disp |=
pATIHW->shadow_h_total_disp & CRTC_H_DISP;
}
pATIHW->crtc_h_total_disp &= ~CRTC_H_TOTAL;
pATIHW->crtc_h_total_disp |=
pATIHW->shadow_h_total_disp & CRTC_H_TOTAL;
pATIHW->crtc_h_sync_strt_wid =
pATIHW->shadow_h_sync_strt_wid;
if (pATIHW->lcd_gen_ctrl & USE_SHADOWED_VEND)
{
pATIHW->crtc_v_total_disp &= ~CRTC_V_DISP;
pATIHW->crtc_v_total_disp |=
pATIHW->shadow_v_total_disp & CRTC_V_DISP;
}
if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
{
pATIHW->crtc_v_total_disp &= ~CRTC_V_TOTAL;
pATIHW->crtc_v_total_disp |=
pATIHW->shadow_v_total_disp & CRTC_V_TOTAL;
}
}
if (!(pATIHW->lcd_gen_ctrl & DONT_SHADOW_VPAR))
pATIHW->crtc_v_sync_strt_wid =
pATIHW->shadow_v_sync_strt_wid;
HDisplay = GetBits(pATIHW->crtc_h_total_disp, CRTC_H_DISP) +
GetBits(pATIHW->ovr_wid_left_right, OVR_WID_LEFT) +
GetBits(pATIHW->ovr_wid_left_right, OVR_WID_RIGHT);
VDisplay = GetBits(pATIHW->crtc_v_total_disp, CRTC_V_DISP) +
GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_TOP) +
GetBits(pATIHW->ovr_wid_top_bottom, OVR_WID_BOTTOM);
pATI->LCDHSyncStart =
(GetBits(pATIHW->crtc_h_sync_strt_wid,
CRTC_H_SYNC_STRT_HI) *
(MaxBits(CRTC_H_SYNC_STRT) + 1)) +
GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_STRT) -
HDisplay;
pATI->LCDHSyncWidth =
GetBits(pATIHW->crtc_h_sync_strt_wid, CRTC_H_SYNC_WID);
pATI->LCDHBlankWidth =
GetBits(pATIHW->crtc_h_total_disp, CRTC_H_TOTAL) -
HDisplay;
pATI->LCDVSyncStart =
GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_STRT) -
VDisplay;
pATI->LCDVSyncWidth =
GetBits(pATIHW->crtc_v_sync_strt_wid, CRTC_V_SYNC_WID);
pATI->LCDVBlankWidth =
GetBits(pATIHW->crtc_v_total_disp, CRTC_V_TOTAL) -
VDisplay;
HDisplay++;
VDisplay++;
}
if (pATI->Chip == ATI_CHIP_264LT)
{
outr(LCD_GEN_CTRL, pATIHW->lcd_gen_ctrl);
}
else
{
ATIMach64PutLCDReg(LCD_GEN_CNTL, pATIHW->lcd_gen_ctrl);
outr(LCD_INDEX, pATIHW->lcd_index);
}
HDisplay <<= 3;
pATI->LCDHSyncStart <<= 3;
pATI->LCDHSyncWidth <<= 3;
pATI->LCDHBlankWidth <<= 3;
if ((pATIHW->horz_stretching &
(HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) ==
HORZ_STRETCH_EN)
{
if (pATIHW->horz_stretching & HORZ_STRETCH_MODE)
{
if (pATIHW->horz_stretching & HORZ_STRETCH_BLEND)
{
HDisplay =
(HDisplay * (MaxBits(HORZ_STRETCH_BLEND) + 1)) /
GetBits(pATIHW->horz_stretching,
HORZ_STRETCH_BLEND);
}
}
else if (((pATIHW->horz_stretching & HORZ_STRETCH_LOOP) >
HORZ_STRETCH_LOOP15) ||
(pATIHW->horz_stretching &
SetBits(1, HORZ_STRETCH_RATIO)))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Ignoring invalid horizontal stretch ratio in mode on"
" server entry.\n");
}
else
{
IOValue =
GetBits(pATIHW->horz_stretching, HORZ_STRETCH_RATIO);
switch (GetBits(pATIHW->horz_stretching,
HORZ_STRETCH_LOOP))
{
case GetBits(HORZ_STRETCH_LOOP09, HORZ_STRETCH_LOOP):
i = 9;
IOValue &= (1 << 9) - 1;
break;
case GetBits(HORZ_STRETCH_LOOP11, HORZ_STRETCH_LOOP):
i = 11;
IOValue &= (1 << 11) - 1;
break;
case GetBits(HORZ_STRETCH_LOOP12, HORZ_STRETCH_LOOP):
i = 12;
IOValue &= (1 << 12) - 1;
break;
case GetBits(HORZ_STRETCH_LOOP14, HORZ_STRETCH_LOOP):
i = 14;
IOValue &= (1 << 14) - 1;
break;
case GetBits(HORZ_STRETCH_LOOP15, HORZ_STRETCH_LOOP):
default:
i = 15;
IOValue &= (1 << 15) - 1;
break;
}
if (IOValue)
{
j = (IOValue >> 1) & 0x36DBU;
j = IOValue - j - ((j >> 1) & 0x36DBU);
j = ((j + (j >> 3)) & 0x71C7U) % 0x3FU;
HDisplay = (HDisplay * i) / j;
}
}
}
if ((pATIHW->vert_stretching & VERT_STRETCH_EN) &&
!(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
{
if ((pATIHW->vert_stretching & VERT_STRETCH_USE0) ||
(VDisplay <= 350))
IOValue =
GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO0);
else if (VDisplay <= 400)
IOValue =
GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO1);
else if ((VDisplay <= 480) ||
!(pATIHW->ext_vert_stretch & VERT_STRETCH_RATIO3))
IOValue =
GetBits(pATIHW->vert_stretching, VERT_STRETCH_RATIO2);
else
IOValue =
GetBits(pATIHW->ext_vert_stretch, VERT_STRETCH_RATIO3);
if (IOValue)
VDisplay =
(VDisplay * (MaxBits(VERT_STRETCH_RATIO0) + 1)) /
IOValue;
}
if (!pATI->LCDHorizontal)
{
if ((pATIHW->horz_stretching &
(HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
(HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
pATI->LCDHorizontal = HDisplay;
}
else if (pATI->LCDHorizontal != (int)HDisplay)
{
if ((pATIHW->horz_stretching &
(HORZ_STRETCH_EN | AUTO_HORZ_RATIO)) !=
(HORZ_STRETCH_EN | AUTO_HORZ_RATIO))
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Inconsistent panel horizontal dimension:"
" %d and %d.\n", pATI->LCDHorizontal, HDisplay);
HDisplay = pATI->LCDHorizontal;
}
if (!pATI->LCDVertical)
{
if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
!(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
pATI->LCDVertical = VDisplay;
}
else if (pATI->LCDVertical != (int)VDisplay)
{
if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) ||
!(pATIHW->ext_vert_stretch & AUTO_VERT_RATIO))
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Inconsistent panel vertical dimension: %d and %d.\n",
pATI->LCDVertical, VDisplay);
VDisplay = pATI->LCDVertical;
}
if (!pATI->LCDHorizontal || !pATI->LCDVertical)
{
if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Unable to determine dimensions of panel (ID %d).\n",
pATI->LCDPanelID);
else
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Unable to determine dimensions of panel.\n");
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
if (!(pATIHW->horz_stretching & HORZ_STRETCH_EN) &&
(pATI->LCDHorizontal > (int)HDisplay))
{
HDisplay = pATI->LCDHorizontal - HDisplay;
if (pATI->LCDHSyncStart >= HDisplay)
pATI->LCDHSyncStart -= HDisplay;
else
pATI->LCDHSyncStart = 0;
pATI->LCDHBlankWidth -= HDisplay;
HDisplay = pATI->LCDHSyncStart + pATI->LCDHSyncWidth;
if (pATI->LCDHBlankWidth < HDisplay)
pATI->LCDHBlankWidth = HDisplay;
}
if (!(pATIHW->vert_stretching & VERT_STRETCH_EN) &&
(pATI->LCDVertical > (int)VDisplay))
{
VDisplay = pATI->LCDVertical - VDisplay;
if (pATI->LCDVSyncStart >= VDisplay)
pATI->LCDVSyncStart -= VDisplay;
else
pATI->LCDVSyncStart = 0;
pATI->LCDVBlankWidth -= VDisplay;
VDisplay = pATI->LCDVSyncStart + pATI->LCDVSyncWidth;
if (pATI->LCDVBlankWidth < VDisplay)
pATI->LCDVBlankWidth = VDisplay;
}
if (pATI->LCDPanelID || (pATI->Chip <= ATI_CHIP_264LTPRO))
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%dx%d panel (ID %d) detected.\n",
pATI->LCDHorizontal, pATI->LCDVertical, pATI->LCDPanelID);
else
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"%dx%d panel detected.\n",
pATI->LCDHorizontal, pATI->LCDVertical);
if (LCDPanelInfo)
{
for (i = 0; i < 24; i++)
Buffer[i] = BIOSByte(LCDPanelInfo + 1 + i);
for (; --i >= 0; )
if (Buffer[i] && Buffer[i] != ' ')
{
Buffer[i + 1] = '\0';
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"Panel model %s.\n", Buffer);
break;
}
}
ClockMask = PLL_VCLK0_XDIV << pATIHW->clock;
PostMask = PLL_VCLK0_POST_DIV << (pATIHW->clock * 2);
i = GetBits(ATIMach64GetPLLReg(PLL_XCLK_CNTL), ClockMask);
i *= MaxBits(PLL_VCLK0_POST_DIV) + 1;
i |= GetBits(ATIMach64GetPLLReg(PLL_VCLK_POST_DIV), PostMask);
Numerator = ATIMach64GetPLLReg(PLL_VCLK0_FB_DIV + pATIHW->clock) *
pATI->ReferenceNumerator;
Denominator = pATI->ClockDescriptor.MinM *
pATI->ReferenceDenominator *
pATI->ClockDescriptor.PostDividers[i];
pATI->LCDClock = ATIDivide(Numerator, Denominator, 1, 0);
xf86DrvMsg(pScreenInfo->scrnIndex, X_PROBED,
"Panel clock is %.3f MHz.\n",
(double)(pATI->LCDClock) / 1000.0);
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using digital flat panel interface%s.\n",
pATI->OptionCRTDisplay ?
" to display on both CRT and panel" : "");
}
}
pScreenInfo->videoRam = pATI->VideoRAM;
#ifndef AVOID_CPIO
AcceleratorVideoRAM = pScreenInfo->videoRam;
if (pATI->Chip == ATI_CHIP_VGA)
{
if (pATI->depth <= 4)
VGAVideoRAM = 256;
else
VGAVideoRAM = 64;
if ((pGDev->videoRam > 0) && (pGDev->videoRam < VGAVideoRAM))
VGAVideoRAM = pGDev->videoRam;
}
else if (pATI->CPIO_VGAWonder)
{
if (pATI->Chip <= ATI_CHIP_18800_1)
{
VGAVideoRAM =
videoRamSizes[GetBits(ATIGetExtReg(0xBBU), 0x20U) + 1];
if (AcceleratorVideoRAM > 512)
AcceleratorVideoRAM = 512;
}
else
{
IOValue = ATIGetExtReg(0xB0U);
if (IOValue & 0x08U)
VGAVideoRAM = 1024;
else if (IOValue & 0x10U)
VGAVideoRAM = 512;
else
VGAVideoRAM = 256;
if (AcceleratorVideoRAM > 1024)
AcceleratorVideoRAM = 1024;
}
}
if (!AcceleratorVideoRAM)
{
pScreenInfo->videoRam = pATI->VideoRAM = VGAVideoRAM;
if ((pATI->depth <= 4) &&
(pATI->Chip <= ATI_CHIP_18800_1) &&
(VGAVideoRAM > 256))
{
if (pATI->OptionDevel)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"Virtual resolutions requiring more than %s kB\n of video"
" memory might not function properly.\n",
(pATI->depth == 1) ? "64" : "256");
}
else
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"VideoRAM reduced to 256 kB due to hardware"
" limitations.\n");
pScreenInfo->videoRam = 256;
}
}
}
else if ((pATI->NewHW.crtc == ATI_CRTC_MACH64) ||
(pATI->Chip >= ATI_CHIP_264CT))
#endif
{
#ifndef AVOID_CPIO
if (pATI->depth >= 8)
#endif
{
pATIHW->config_cntl = inr(CONFIG_CNTL);
pATI->LinearBase =
GetBits(pATIHW->config_cntl, CFG_MEM_AP_LOC) << 22;
if ((pATIHW->config_cntl & CFG_MEM_AP_SIZE) != CFG_MEM_AP_SIZE)
{
pATI->LinearSize =
GetBits(pATIHW->config_cntl, CFG_MEM_AP_SIZE) << 22;
if (pATI->LinearBase && !pATI->LinearSize)
{
if ((pATI->Chip <= ATI_CHIP_88800GXD) &&
(pATI->VideoRAM < 4096))
pATI->LinearSize = 4 * 1024 * 1024;
else
pATI->LinearSize = 8 * 1024 * 1024;
}
}
#ifndef AVOID_CPIO
if (!pVideo)
{
if (pATI->Chip == ATI_CHIP_88800CX)
IOValue = ~((CARD32)((1 << 23) - 1));
else if (pATI->Chip >= ATI_CHIP_88800GXE)
IOValue = ~((CARD32)((1 << 24) - 1));
else if (pATI->VideoRAM >= 4096)
IOValue = ~((CARD32)((1 << 23) - 1));
else
IOValue = ~((CARD32)((1 << 22) - 1));
IOValue &= pGDev->MemBase;
if (IOValue &&
(IOValue <= (CARD32)(MaxBits(CFG_MEM_AP_LOC) << 22)))
pATI->LinearBase = IOValue;
if (!pATI->LinearBase)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Linear aperture not configured. Specify \"MemBase\""
" override in XF86Config \"Device\" section.\n");
}
else
{
if (!pATI->LinearSize)
{
if ((pATI->Chip <= ATI_CHIP_88800GXD) &&
(pATI->VideoRAM < 4096))
pATI->LinearSize = 4 * 1024 * 1024;
else
pATI->LinearSize = 8 * 1024 * 1024;
}
Resources[0].type = ResExcMemBlock | ResBus;
Resources[0].rBegin = pATI->LinearBase;
Resources[0].rEnd =
pATI->LinearBase + pATI->LinearSize - 1;
if (xf86RegisterResources(pATI->iEntity, Resources,
ResNone))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to register %d MB linear aperture at"
" 0x%08lX.\n", pATI->LinearSize >> 10,
pATI->LinearBase);
pATI->LinearSize = 0;
}
}
}
#endif
if (pATI->LinearBase && pATI->LinearSize)
{
if (!pATI->Block0Base)
{
pATI->Block0Base =
pATI->LinearBase + pATI->LinearSize - 0x00000400U;
pATI->MMIOInLinear = TRUE;
}
AcceleratorVideoRAM = pATI->LinearSize >> 10;
if (pATI->MMIOInLinear || (pATI->Chip < ATI_CHIP_264VTB))
AcceleratorVideoRAM -= 2;
ServerVideoRAM = pATI->VideoRAM;
if (pATI->Cursor > ATI_CURSOR_SOFTWARE)
{
if (ServerVideoRAM > AcceleratorVideoRAM)
ServerVideoRAM = AcceleratorVideoRAM;
ServerVideoRAM--;
pATI->CursorOffset = ServerVideoRAM << 10;
pATI->CursorBase = pATI->LinearBase + pATI->CursorOffset;
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Storing hardware cursor image at 0x%08lX.\n",
pATI->CursorBase);
}
#ifndef AVOID_CPIO
if (pATI->OptionLinear)
#endif
{
CARD32 PageSize = getpagesize() >> 10;
#if X_BYTE_ORDER == X_LITTLE_ENDIAN
if (pATI->MMIOInLinear)
AcceleratorVideoRAM -= AcceleratorVideoRAM % PageSize;
#else
pATI->LinearBase += 0x00800000U;
AcceleratorVideoRAM = pATI->LinearSize >> 10;
#endif
if (ServerVideoRAM > AcceleratorVideoRAM)
ServerVideoRAM = AcceleratorVideoRAM;
else if (AcceleratorVideoRAM > pATI->VideoRAM)
AcceleratorVideoRAM = pATI->VideoRAM;
PageSize--;
AcceleratorVideoRAM =
(AcceleratorVideoRAM + PageSize) & ~PageSize;
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using %d MB linear aperture at 0x%08lX.\n",
pATI->LinearSize >> 20, pATI->LinearBase);
ApertureSize = pATI->LinearSize =
AcceleratorVideoRAM << 10;
}
if (ServerVideoRAM < pATI->VideoRAM)
{
pScreenInfo->videoRam = ServerVideoRAM;
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"Virtual resolutions will be limited to %d kB\n due to"
" linear aperture size and/or placement of hardware"
" cursor image area.\n",
ServerVideoRAM);
}
}
}
#ifndef AVOID_CPIO
if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
{
pATI->UseSmallApertures = TRUE;
if (pATI->depth <= 4)
{
pATI->NewHW.SetBank = ATIMach64SetBankPlanar;
pATI->BankInfo.SetSourceBank = ATIMach64SetReadPlanar;
pATI->BankInfo.SetDestinationBank = ATIMach64SetWritePlanar;
pATI->BankInfo.SetSourceAndDestinationBanks =
ATIMach64SetReadWritePlanar;
}
else
{
pATI->NewHW.SetBank = ATIMach64SetBankPacked;
pATI->BankInfo.SetSourceBank = ATIMach64SetReadPacked;
pATI->BankInfo.SetDestinationBank = ATIMach64SetWritePacked;
pATI->BankInfo.SetSourceAndDestinationBanks =
ATIMach64SetReadWritePacked;
}
if (!pATI->Block0Base &&
((pATI->Chip < ATI_CHIP_264CT) ||
(pATI->Chip >= ATI_CHIP_264VT) ||
pATI->OptionDevel))
pATI->Block0Base = 0x000BFC00U;
}
if (!pATI->OptionLinear)
pATI->LinearBase = 0;
#endif
if (!pATI->LinearBase || !pATI->LinearSize)
{
#ifndef AVOID_CPIO
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
#endif
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_ERROR,
"Linear aperture not available.\n");
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
#ifndef AVOID_CPIO
pATI->LinearBase = pATI->LinearSize = 0;
#endif
}
if (pATI->Block0Base)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using Block 0 MMIO aperture at 0x%08lX.\n", pATI->Block0Base);
if (pATI->Chip >= ATI_CHIP_264VT)
{
pATI->Block1Base = pATI->Block0Base - 0x00000400U;
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using Block 1 MMIO aperture at 0x%08lX.\n",
pATI->Block1Base);
}
}
}
#ifndef AVOID_CPIO
else
if (((pATI->Chip < ATI_CHIP_68800) || (pATI->Chip > ATI_CHIP_68800AX)) &&
(AcceleratorVideoRAM < pScreenInfo->videoRam))
{
if (pATI->OptionDevel)
{
if (pATI->depth == 1)
AcceleratorVideoRAM /= 4;
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"Virtual resolutions requiring more than %d kB\n of video"
" memory might not function correctly.\n",
AcceleratorVideoRAM);
}
else
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"VideoRAM reduced to %d kB due to hardware limitations.\n",
AcceleratorVideoRAM);
pScreenInfo->videoRam = AcceleratorVideoRAM;
}
}
if (pATI->OptionLinear)
{
if (!pATI->LinearBase)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Linear aperture not supported in this configuration.\n");
pATI->OptionLinear = FALSE;
}
else if (pATI->VGAAdapter != ATI_ADAPTER_NONE)
{
pResources = xf86SetOperatingState(resVgaMem, pATI->iEntity,
ResUnusedOpr);
if (pResources)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Logic error setting operating state for VGA memory"
" aperture.\n");
xf86FreeResList(pResources);
}
}
}
#endif
if ((pATI->Cursor > ATI_CURSOR_SOFTWARE) && !pATI->CursorBase)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Unable to store hardware cursor image. Reverting to software"
" cursor.\n");
pATI->Cursor = ATI_CURSOR_SOFTWARE;
}
ATILock(pATI);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
if (!ATIMapApertures(pScreenInfo->scrnIndex, pATI))
return FALSE;
ATIUnlock(pATI);
if (pATI->OptionAccel)
{
#ifndef AVOID_CPIO
if (!pATI->Block0Base || (pATI->NewHW.crtc == ATI_CRTC_VGA))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Acceleration not supported in this configuration.\n");
pATI->OptionAccel = FALSE;
}
else
#endif
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"MMIO write caching %sabled.\n",
pATI->OptionMMIOCache ? "en" : "dis");
}
}
#ifndef AVOID_CPIO
if (pATI->Adapter >= ATI_ADAPTER_MACH32)
#endif
{
if (pATI->Chip >= ATI_CHIP_264CT)
ATIReportMemory(pScreenInfo, pATI,
ATIMemoryTypeNames_264xT[pATI->MemoryType]);
else if (pATI->Chip == ATI_CHIP_88800CX)
ATIReportMemory(pScreenInfo, pATI,
ATIMemoryTypeNames_88800CX[pATI->MemoryType]);
else
ATIReportMemory(pScreenInfo, pATI,
ATIMemoryTypeNames_Mach[pATI->MemoryType]);
}
#ifndef AVOID_CPIO
else if (pATI->Adapter >= ATI_ADAPTER_V3)
{
ATIReportMemory(pScreenInfo, pATI,
(ATIGetExtReg(0xB7U) & 0x04U) ? "DRAM" : "VRAM");
}
else
{
ATIReportMemory(pScreenInfo, pATI, "video memory");
}
#endif
#ifndef AVOID_CPIO
if (pATI->VGAAdapter == ATI_ADAPTER_NONE)
#endif
{
pATIHW->crtc = pATI->NewHW.crtc;
#ifndef AVOID_CPIO
pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
pATI->BankInfo.BankSize = 0;
#endif
}
#ifndef AVOID_CPIO
else
{
pATIHW->crtc = ATI_CRTC_VGA;
#if 0
if (pATI->ChipHasSUBSYS_CNTL)
{
}
else
#endif
if ((pATI->Chip >= ATI_CHIP_88800GXC) &&
(pATI->LockData.crtc_gen_cntl & CRTC_EXT_DISP_EN))
{
pATIHW->crtc = ATI_CRTC_MACH64;
}
if (pATI->depth <= 4)
{
pATI->BankInfo.nBankDepth = 1;
pATI->NewHW.nPlane = 4;
}
else
{
pATI->BankInfo.nBankDepth = pATI->depth;
pATI->NewHW.nPlane = 1;
}
if ((pATIHW->crtc != ATI_CRTC_VGA) || (GetReg(SEQX, 0x04U) & 0x08U))
pATIHW->nPlane = 1;
else
pATIHW->nPlane = 4;
pATIHW->nBank = ATIDivide(pATI->VideoRAM,
pATIHW->nPlane * pATI->BankInfo.BankSize, 10, 1);
pATI->NewHW.nBank = ATIDivide(pATI->VideoRAM,
pATI->NewHW.nPlane * pATI->BankInfo.BankSize, 10, 1);
if (pATI->VGAAdapter == ATI_ADAPTER_VGA)
{
pATIHW->SetBank = pATI->NewHW.SetBank =
(ATIBankProcPtr)NoopDDA;
pATIHW->nBank = pATI->NewHW.nBank = 1;
}
else if (!pATI->UseSmallApertures)
{
pATIHW->SetBank = pATI->NewHW.SetBank;
}
else if ((pATIHW->crtc == ATI_CRTC_VGA) &&
!(pATI->LockData.config_cntl & CFG_MEM_VGA_AP_EN))
{
pATIHW->SetBank = (ATIBankProcPtr)NoopDDA;
pATIHW->nBank = 1;
}
else if (pATIHW->nPlane == 1)
{
pATIHW->SetBank = ATIMach64SetBankPacked;
}
else
{
pATIHW->SetBank = ATIMach64SetBankPlanar;
}
if (((ApertureSize * pATI->depth) / pATI->BankInfo.nBankDepth) >=
(unsigned)(pScreenInfo->videoRam * 1024))
pATI->BankInfo.BankSize = 0;
}
#endif
if (pATI->OptionShadowFB)
{
#ifndef AVOID_CPIO
if (pATI->BankInfo.BankSize)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Cannot shadow a banked frame buffer.\n");
pATI->OptionShadowFB = FALSE;
}
else if (pATI->depth < 8)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Cannot shadow a planar frame buffer.\n");
pATI->OptionShadowFB = FALSE;
}
else
#endif
if (pATI->OptionAccel)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Cannot shadow an accelerated frame buffer.\n");
pATI->OptionShadowFB = FALSE;
}
else
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Using shadow frame buffer.\n");
}
}
if ((pATI->Chip >= ATI_CHIP_264VTB) &&
!ATIDSPPreInit(pScreenInfo->scrnIndex, pATI))
{
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
if (pATI->ClockDescriptor.MaxN > 0)
{
Numerator = pATI->ClockDescriptor.MaxN * pATI->ReferenceNumerator;
Denominator = pATI->ClockDescriptor.MinM * pATI->ReferenceDenominator *
pATI->ClockDescriptor.PostDividers[0];
if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
Numerator <<= 1;
else if (pATI->depth > 8)
Denominator *= (pATI->bitsPerPixel / 8);
ATIClockRange.maxClock = (Numerator / (Denominator * 1000)) * 1000;
Numerator = pATI->ClockDescriptor.MinN * pATI->ReferenceNumerator;
Denominator = pATI->ClockDescriptor.MaxM * pATI->ReferenceDenominator *
pATI->ClockDescriptor.PostDividers[pATI->ClockDescriptor.NumD - 1];
if (pATI->ProgrammableClock == ATI_CLOCK_INTERNAL)
Numerator <<= 1;
ATIClockRange.minClock = (Numerator / (Denominator * 1000)) * 1000;
if (pATI->XCLKFeedbackDivider)
{
Numerator = pATI->XCLKFeedbackDivider * 2 *
pATI->ReferenceNumerator;
Denominator = pATI->ClockDescriptor.MinM *
pATI->XCLKReferenceDivider * pATI->ReferenceDenominator;
#ifndef AVOID_CPIO
if (pATI->depth >= 8)
#endif
{
Denominator *= pATI->bitsPerPixel / 4;
}
i = (6 - 2) - pATI->XCLKPostDivider;
#ifndef AVOID_CPIO
if (pATI->NewHW.crtc == ATI_CRTC_VGA)
i--;
#endif
i = (ATIDivide(Numerator, Denominator, i, -1) / 1000) * 1000;
if (i < ATIClockRange.maxClock)
ATIClockRange.maxClock = i;
}
}
if ((pATI->DAC & ~0x0FU) == ATI_DAC_INTERNAL)
{
int DacSpeed;
switch (pATI->bitsPerPixel)
{
case 15:
case 16:
DacSpeed = pGDev->dacSpeeds[DAC_BPP16];
break;
case 24:
DacSpeed = pGDev->dacSpeeds[DAC_BPP24];
break;
case 32:
DacSpeed = pGDev->dacSpeeds[DAC_BPP32];
break;
default:
DacSpeed = 0;
break;
}
if (!DacSpeed)
DacSpeed = pGDev->dacSpeeds[DAC_BPP8];
if (DacSpeed < ATIClockRange.maxClock)
{
DefaultmaxClock = 135000;
if (pATI->depth > 8)
DefaultmaxClock = 80000;
if ((pATI->Chip >= ATI_CHIP_264VTB) &&
(pATI->Chip != ATI_CHIP_Mach64))
{
if ((pATI->Chip >= ATI_CHIP_264VT4) &&
(pATI->Chip != ATI_CHIP_264LTPRO))
DefaultmaxClock = 230000;
else if (pATI->Chip >= ATI_CHIP_264VT3)
DefaultmaxClock = 200000;
else
DefaultmaxClock = 170000;
}
if (DacSpeed > DefaultmaxClock)
ATIClockRange.maxClock = DacSpeed;
else if (DefaultmaxClock < ATIClockRange.maxClock)
ATIClockRange.maxClock = DefaultmaxClock;
}
}
else
{
switch(pATI->DAC)
{
case ATI_DAC_STG1700:
case ATI_DAC_STG1702:
case ATI_DAC_STG1703:
DefaultmaxClock = 110000;
break;
case ATI_DAC_IBMRGB514:
pATI->maxClock = 220000;
#ifndef AVOID_CPIO
if (pATI->NewHW.crtc == ATI_CRTC_VGA)
{
DefaultmaxClock = 100000;
}
else
#endif
{
DefaultmaxClock = 220000;
}
break;
default:
#ifndef AVOID_CPIO
if ((pATI->Chip == ATI_CHIP_18800) ||
(pATI->Chip == ATI_CHIP_18800_1))
{
DefaultmaxClock = 40000;
}
else if (pATI->CPIO_VGAWonder &&
(pATI->VideoRAM < 1024) &&
(pATI->depth >= 8))
{
DefaultmaxClock =
(GetBits(BIOSByte(0x44U), 0x04U) * 5000) + 40000;
}
else
#endif
{
DefaultmaxClock = 80000;
}
break;
}
if (DefaultmaxClock < ATIClockRange.maxClock)
ATIClockRange.maxClock = DefaultmaxClock;
}
if (pATI->ClockDescriptor.MaxN <= 0)
{
ATIClockRange.maxClock = DefaultmaxClock;
xf86DrvMsg(pScreenInfo->scrnIndex, X_INFO,
"Maximum pixel clock: %.3f MHz.\n",
(double)ATIClockRange.maxClock / 1000.0);
}
ATIClockPreInit(pScreenInfo, pATI, pGDev, &ATIClockRange);
if (pATI->ProgrammableClock > ATI_CLOCK_FIXED)
Strategy = LOOKUP_BEST_REFRESH;
#ifdef AVOID_CPIO
if (pATI->Chip >= ATI_CHIP_264CT)
{
minPitch = 8;
}
#else
if ((pATI->depth >= 8) && (pATI->Chip >= ATI_CHIP_264CT))
{
minPitch = 8;
}
else if (pATI->CPIO_VGAWonder &&
(pATI->Chip <= ATI_CHIP_18800_1) &&
(pATI->VideoRAM == 256) &&
(pATI->depth >= 8))
{
minPitch = 32;
maxPitch = 0x3FU;
}
#endif
else
{
minPitch = 16;
}
pATI->pitchInc = minPitch;
#ifndef AVOID_CPIO
if (pATI->depth >= 8)
#endif
{
pATI->pitchInc *= pATI->bitsPerPixel;
}
switch (pATI->NewHW.crtc)
{
#ifndef AVOID_CPIO
case ATI_CRTC_VGA:
if (pATI->Adapter <= ATI_ADAPTER_VGA)
ATIClockRange.interlaceAllowed = FALSE;
pScreenInfo->maxHValue = (0xFFU + 1) << 3;
pScreenInfo->maxVValue = 0x03FFU + 1;
if (pATI->Adapter > ATI_ADAPTER_VGA)
{
pScreenInfo->maxVValue <<= 1;
if (ATIClockRange.interlaceAllowed &&
(pATI->Chip < ATI_CHIP_264CT))
pScreenInfo->maxVValue <<= 1;
}
if (ATIClockRange.interlaceAllowed &&
(pATI->Chip <= ATI_CHIP_28800_6))
{
if (minPitch == 32)
pATI->MaximumInterlacedPitch = 0x1FU * 32;
else
pATI->MaximumInterlacedPitch = 0x7FU * minPitch;
}
Strategy |= LOOKUP_CLKDIV2;
break;
#endif
case ATI_CRTC_MACH64:
pScreenInfo->maxHValue = (MaxBits(CRTC_H_TOTAL) + 1) << 3;
if (pATI->Chip < ATI_CHIP_264VT)
{
ATIClockRange.doubleScanAllowed = FALSE;
pScreenInfo->maxHValue >>= 1;
}
pScreenInfo->maxVValue = MaxBits(CRTC_V_TOTAL) + 1;
maxPitch = MaxBits(CRTC_PITCH);
break;
default:
break;
}
maxPitch *= minPitch;
if (pATI->OptionAccel)
{
if (maxPitch > (ATIMach64MaxX / pATI->XModifier))
maxPitch = ATIMach64MaxX / pATI->XModifier;
maxHeight = ATIMach64MaxY;
if ((pATI->Chip >= ATI_CHIP_264CT) &&
((pATI->Chip >= ATI_CHIP_264VTB) ||
(pATI->MemoryType >= MEM_264_SGRAM)))
pATI->pitchInc = pATI->XModifier * (64 * 8);
}
if (pATI->OptionPanelDisplay && (pATI->LCDPanelID >= 0))
{
Strategy |= LOOKUP_OPTIONAL_TOLERANCES;
if (ModeType == M_T_BUILTIN)
{
pMode = (DisplayModePtr)xnfcalloc(1, SizeOf(DisplayModeRec));
pMode->name = "Native panel mode";
pMode->type = M_T_BUILTIN;
pMode->Clock = pATI->LCDClock;
pMode->HDisplay = pATI->LCDHorizontal;
pMode->VDisplay = pATI->LCDVertical;
pMode->HSyncStart = pMode->HDisplay;
pMode->HSyncEnd = pMode->HSyncStart + minPitch;
pMode->HTotal = pMode->HSyncEnd + minPitch;
pMode->VSyncStart = pMode->VDisplay;
pMode->VSyncEnd = pMode->VSyncStart + 1;
pMode->VTotal = pMode->VSyncEnd + 1;
pMode->CrtcHDisplay = pMode->HDisplay;
pMode->CrtcHBlankStart = pMode->HDisplay;
pMode->CrtcHSyncStart = pMode->HSyncStart;
pMode->CrtcHSyncEnd = pMode->HSyncEnd;
pMode->CrtcHBlankEnd = pMode->HTotal;
pMode->CrtcHTotal = pMode->HTotal;
pMode->CrtcVDisplay = pMode->VDisplay;
pMode->CrtcVBlankStart = pMode->VDisplay;
pMode->CrtcVSyncStart = pMode->VSyncStart;
pMode->CrtcVSyncEnd = pMode->VSyncEnd;
pMode->CrtcVBlankEnd = pMode->VTotal;
pMode->CrtcVTotal = pMode->VTotal;
if (!pScreenInfo->monitor->Modes)
{
pScreenInfo->monitor->Modes = pMode;
}
else
{
pScreenInfo->monitor->Last->next = pMode;
pMode->prev = pScreenInfo->monitor->Last;
}
pScreenInfo->monitor->Last = pMode;
}
if (pScreenInfo->monitor->nHsync > 0)
{
double hsync = (double)pATI->LCDClock /
(pATI->LCDHorizontal + pATI->LCDHBlankWidth);
for (i = 0; ; i++)
{
if (i >= pScreenInfo->monitor->nHsync)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"Conflicting XF86Config HorizSync specification(s)"
" ignored.\n");
break;
}
if ((hsync >= pScreenInfo->monitor->hsync[i].lo) &&
(hsync <= pScreenInfo->monitor->hsync[i].hi))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Extraneous XF86Config HorizSync specification(s)"
" ignored.\n");
break;
}
}
pScreenInfo->monitor->nHsync = 0;
}
if (pScreenInfo->monitor->nVrefresh > 0)
{
double vrefresh = ((double)pATI->LCDClock * 1000.0) /
((pATI->LCDHorizontal + pATI->LCDHBlankWidth) *
(pATI->LCDVertical + pATI->LCDVBlankWidth));
for (i = 0; ; i++)
{
if (i >= pScreenInfo->monitor->nVrefresh)
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_NOTICE,
"Conflicting XF86Config VertRefresh specification(s)"
" ignored.\n");
break;
}
if ((vrefresh >= pScreenInfo->monitor->vrefresh[i].lo) &&
(vrefresh <= pScreenInfo->monitor->vrefresh[i].hi))
{
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Extraneous XF86Config VertRefresh specification(s)"
" ignored.\n");
break;
}
}
pScreenInfo->monitor->nVrefresh = 0;
}
}
i = xf86ValidateModes(pScreenInfo,
pScreenInfo->monitor->Modes, pScreenInfo->display->modes,
&ATIClockRange, NULL, minPitch, maxPitch,
pATI->pitchInc, 0, maxHeight,
pScreenInfo->display->virtualX, pScreenInfo->display->virtualY,
ApertureSize, Strategy);
if (i <= 0)
{
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
xf86PruneDriverModes(pScreenInfo);
pScreenInfo->currentMode = pScreenInfo->modes;
xf86PrintModes(pScreenInfo);
xf86SetDpi(pScreenInfo, 0, 0);
if (!ATILoadModules(pScreenInfo, pATI))
{
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return FALSE;
}
pATI->displayWidth = pScreenInfo->displayWidth;
ATIAdjustPreInit(pATI);
MinX = pScreenInfo->virtualX - pATI->AdjustMaxX;
MinY = pScreenInfo->virtualY - pATI->AdjustMaxY;
pMode = pScreenInfo->modes;
do
{
if ((pMode->VDisplay <= MinY) &&
((pMode->VDisplay < MinY) || (pMode->HDisplay < MinX)))
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Mode \"%s\" too small to scroll to bottom right corner of"
" virtual resolution.\n", pMode->name);
else if ((pMode->HDisplay & ~pATI->AdjustMask) / pScreenInfo->xInc)
xf86DrvMsg(pScreenInfo->scrnIndex, X_WARNING,
"Mode \"%s\" cannot scroll to bottom right corner of virtual"
" resolution.\n Horizontal dimension not a multiple of %ld.\n",
pMode->name, ~pATI->AdjustMask + 1);
} while ((pMode = pMode->next) != pScreenInfo->modes);
ATIXVPreInit(pATI);
ATIModePreInit(pScreenInfo, pATI, &pATI->NewHW);
ATII2CPreInit(pScreenInfo, pATI);
if (!pScreenInfo->chipset || !*pScreenInfo->chipset)
pScreenInfo->chipset = (char *)ATIChipsetNames[0];
ATILock(pATI);
ATIPrintNoiseIfRequested(pATI, BIOS, BIOSSize);
ATIUnmapApertures(pScreenInfo->scrnIndex, pATI);
return TRUE;
}