savage_driver.c revision 8697ee19
1ab47cfaaSmrg/*
2ab47cfaaSmrg * Copyright (C) 1994-2000 The XFree86 Project, Inc.  All Rights Reserved.
3ab47cfaaSmrg * Copyright (c) 2003-2006, X.Org Foundation
4ab47cfaaSmrg *
5ab47cfaaSmrg * Permission is hereby granted, free of charge, to any person obtaining a
6ab47cfaaSmrg * copy of this software and associated documentation files (the "Software"),
7ab47cfaaSmrg * to deal in the Software without restriction, including without limitation
8ab47cfaaSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9ab47cfaaSmrg * and/or sell copies of the Software, and to permit persons to whom the
10ab47cfaaSmrg * Software is furnished to do so, subject to the following conditions:
11ab47cfaaSmrg *
12ab47cfaaSmrg * The above copyright notice and this permission notice shall be included in
13ab47cfaaSmrg * all copies or substantial portions of the Software.
14ab47cfaaSmrg *
15ab47cfaaSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16ab47cfaaSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17ab47cfaaSmrg * FITESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
18ab47cfaaSmrg * COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19ab47cfaaSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20ab47cfaaSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21ab47cfaaSmrg * DEALINGS IN THE SOFTWARE.
22ab47cfaaSmrg *
23ab47cfaaSmrg * Except as contained in this notice, the name of the copyright holder(s)
24ab47cfaaSmrg * and author(s) shall not be used in advertising or otherwise to promote
25ab47cfaaSmrg * the sale, use or other dealings in this Software without prior written
26ab47cfaaSmrg * authorization from the copyright holder(s) and author(s).
27ab47cfaaSmrg */
28ab47cfaaSmrg
29ab47cfaaSmrg/**
30ab47cfaaSmrg * \file savage_driver.c
31ab47cfaaSmrg *
32ab47cfaaSmrg * \author Tim Roberts <timr@probo.com>
33ab47cfaaSmrg * \author Ani Joshi <ajoshi@unixbox.com>
34ab47cfaaSmrg *
35ab47cfaaSmrg * \todo Add credits for the 3.3.x authors.
36ab47cfaaSmrg */
37ab47cfaaSmrg
38ab47cfaaSmrg#ifdef HAVE_CONFIG_H
39ab47cfaaSmrg#include "config.h"
40ab47cfaaSmrg#endif
41ab47cfaaSmrg
428697ee19Smrg#include <unistd.h>
438697ee19Smrg#include <errno.h>
448697ee19Smrg
45ab47cfaaSmrg#include "xf86RAC.h"
46ab47cfaaSmrg#include "shadowfb.h"
47ab47cfaaSmrg
48ab47cfaaSmrg#include "globals.h"
49ab47cfaaSmrg#define DPMS_SERVER
50ab47cfaaSmrg#include <X11/extensions/dpms.h>
51ab47cfaaSmrg
52ab47cfaaSmrg#include "xf86xv.h"
53ab47cfaaSmrg
54ab47cfaaSmrg#include "savage_driver.h"
55ab47cfaaSmrg#include "savage_regs.h"
56ab47cfaaSmrg#include "savage_bci.h"
57ab47cfaaSmrg#include "savage_streams.h"
58ab47cfaaSmrg
59ab47cfaaSmrg#define TRANSPARENCY_KEY 0xff;
60ab47cfaaSmrg
61ab47cfaaSmrg#ifdef XF86DRI
62ab47cfaaSmrg#define _XF86DRI_SERVER_
63ab47cfaaSmrg#include "savage_dri.h"
64ab47cfaaSmrg#include "savage_sarea.h"
65ab47cfaaSmrg#endif
66ab47cfaaSmrg
67ab47cfaaSmrg
68ab47cfaaSmrg/*
69ab47cfaaSmrg * prototypes
70ab47cfaaSmrg */
71ab47cfaaSmrgstatic void SavageEnableMMIO(ScrnInfoPtr pScrn);
72ab47cfaaSmrgstatic void SavageDisableMMIO(ScrnInfoPtr pScrn);
73ab47cfaaSmrg
74ab47cfaaSmrgstatic const OptionInfoRec * SavageAvailableOptions(int chipid, int busid);
75ab47cfaaSmrgstatic void SavageIdentify(int flags);
768697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
778697ee19Smrgstatic Bool SavagePciProbe(DriverPtr drv, int entity_num,
788697ee19Smrg			   struct pci_device *dev, intptr_t match_data);
798697ee19Smrg#else
80ab47cfaaSmrgstatic Bool SavageProbe(DriverPtr drv, int flags);
818697ee19Smrgstatic int LookupChipID(PciChipsets* pset, int ChipID);
828697ee19Smrg#endif
83ab47cfaaSmrgstatic Bool SavagePreInit(ScrnInfoPtr pScrn, int flags);
84ab47cfaaSmrg
85ab47cfaaSmrgstatic Bool SavageEnterVT(int scrnIndex, int flags);
86ab47cfaaSmrgstatic void SavageLeaveVT(int scrnIndex, int flags);
87ab47cfaaSmrgstatic void SavageSave(ScrnInfoPtr pScrn);
88ab47cfaaSmrgstatic void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr, SavageRegPtr, Bool);
89ab47cfaaSmrg
90ab47cfaaSmrgstatic void SavageInitStatus(ScrnInfoPtr pScrn);
91ab47cfaaSmrgstatic void SavageInitShadowStatus(ScrnInfoPtr pScrn);
92ab47cfaaSmrg
93ab47cfaaSmrgstatic Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
94ab47cfaaSmrg			     char **argv);
95ab47cfaaSmrgstatic int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen);
96ab47cfaaSmrgstatic ModeStatus SavageValidMode(int index, DisplayModePtr mode,
97ab47cfaaSmrg				  Bool verbose, int flags);
98ab47cfaaSmrg
99ab47cfaaSmrgvoid SavageDGAInit(ScreenPtr);
100ab47cfaaSmrgstatic Bool SavageMapMem(ScrnInfoPtr pScrn);
101ab47cfaaSmrgstatic void SavageUnmapMem(ScrnInfoPtr pScrn, int All);
102ab47cfaaSmrgstatic Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
103ab47cfaaSmrgstatic Bool SavageCloseScreen(int scrnIndex, ScreenPtr pScreen);
104ab47cfaaSmrgstatic Bool SavageSaveScreen(ScreenPtr pScreen, int mode);
105ab47cfaaSmrgstatic void SavageLoadPalette(ScrnInfoPtr pScrn, int numColors,
106ab47cfaaSmrg			      int *indicies, LOCO *colors,
107ab47cfaaSmrg			      VisualPtr pVisual);
108ab47cfaaSmrgstatic void SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors,
109ab47cfaaSmrg			      int *indicies, LOCO *colors,
110ab47cfaaSmrg			      VisualPtr pVisual);
111ab47cfaaSmrgstatic void SavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b);
112ab47cfaaSmrgstatic void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
113ab47cfaaSmrg			   int min_n2, int max_n2, long freq_min,
114ab47cfaaSmrg			   long freq_max, unsigned int *mdiv,
115ab47cfaaSmrg			   unsigned int *ndiv, unsigned int *r);
116ab47cfaaSmrgvoid SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file);
117ab47cfaaSmrgvoid SavagePrintRegs(ScrnInfoPtr pScrn);
118ab47cfaaSmrgstatic void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags);
119ab47cfaaSmrgstatic Bool SavageDDC1(int scrnIndex);
120ab47cfaaSmrgstatic unsigned int SavageDDC1Read(ScrnInfoPtr pScrn);
121ab47cfaaSmrgstatic void SavageProbeDDC(ScrnInfoPtr pScrn, int index);
122ab47cfaaSmrgstatic void SavageGetTvMaxSize(SavagePtr psav);
1238697ee19Smrgstatic Bool SavagePanningCheck(ScrnInfoPtr pScrn, DisplayModePtr pMode);
124ab47cfaaSmrg#ifdef XF86DRI
125ab47cfaaSmrgstatic Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn);
126ab47cfaaSmrg#endif
127ab47cfaaSmrgstatic void SavageResetStreams(ScrnInfoPtr pScrn);
128ab47cfaaSmrg
129ab47cfaaSmrgextern ScrnInfoPtr gpScrn;
130ab47cfaaSmrg
131ab47cfaaSmrg#define iabs(a)	((int)(a)>0?(a):(-(a)))
132ab47cfaaSmrg
133ab47cfaaSmrg/*#define TRACEON*/
134ab47cfaaSmrg#ifdef TRACEON
135ab47cfaaSmrg#define TRACE(prms)	ErrorF prms
136ab47cfaaSmrg#else
137ab47cfaaSmrg#define TRACE(prms)
138ab47cfaaSmrg#endif
139ab47cfaaSmrg
140ab47cfaaSmrgint gSavageEntityIndex = -1;
141ab47cfaaSmrg
1428697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
1438697ee19Smrg#define SAVAGE_DEVICE_MATCH(d, i) \
1448697ee19Smrg    { 0x5333, (d), PCI_MATCH_ANY, PCI_MATCH_ANY, 0, 0, (i) }
1458697ee19Smrg
1468697ee19Smrgstatic const struct pci_id_match savage_device_match[] = {
1478697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE4,         S3_SAVAGE4),
1488697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE3D,        S3_SAVAGE3D),
1498697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE3D_MV,     S3_SAVAGE3D),
1508697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE2000,      S3_SAVAGE2000),
1518697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE_MX_MV,    S3_SAVAGE_MX),
1528697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE_MX,       S3_SAVAGE_MX),
1538697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE_IX_MV,    S3_SAVAGE_MX),
1548697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SAVAGE_IX,       S3_SAVAGE_MX),
1558697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_PROSAVAGE_PM,    S3_PROSAVAGE),
1568697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_PROSAVAGE_KM,    S3_PROSAVAGE),
1578697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_S3TWISTER_P,     S3_TWISTER),
1588697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_S3TWISTER_K,     S3_TWISTER),
1598697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_MX128,    S3_SUPERSAVAGE),
1608697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_MX64,     S3_SUPERSAVAGE),
1618697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_MX64C,    S3_SUPERSAVAGE),
1628697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_IX128SDR, S3_SUPERSAVAGE),
1638697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_IX128DDR, S3_SUPERSAVAGE),
1648697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_IX64SDR,  S3_SUPERSAVAGE),
1658697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_IX64DDR,  S3_SUPERSAVAGE),
1668697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_IXCSDR,   S3_SUPERSAVAGE),
1678697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_SUPSAV_IXCDDR,   S3_SUPERSAVAGE),
1688697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_PROSAVAGE_DDR,   S3_PROSAVAGEDDR),
1698697ee19Smrg    SAVAGE_DEVICE_MATCH(PCI_CHIP_PROSAVAGE_DDRK,  S3_PROSAVAGEDDR),
1708697ee19Smrg
1718697ee19Smrg    { 0, 0, 0 },
172ab47cfaaSmrg};
1738697ee19Smrg#endif
174ab47cfaaSmrg
175ab47cfaaSmrg/* Supported chipsets */
176ab47cfaaSmrg
177ab47cfaaSmrgstatic SymTabRec SavageChips[] = {
178ab47cfaaSmrg    { PCI_CHIP_SAVAGE4,		"Savage4" },
179ab47cfaaSmrg    { PCI_CHIP_SAVAGE3D,	"Savage3D" },
180ab47cfaaSmrg    { PCI_CHIP_SAVAGE3D_MV,	"Savage3D-MV" },
181ab47cfaaSmrg    { PCI_CHIP_SAVAGE2000,	"Savage2000" },
182ab47cfaaSmrg    { PCI_CHIP_SAVAGE_MX_MV,	"Savage/MX-MV" },
183ab47cfaaSmrg    { PCI_CHIP_SAVAGE_MX,	"Savage/MX" },
184ab47cfaaSmrg    { PCI_CHIP_SAVAGE_IX_MV,	"Savage/IX-MV" },
185ab47cfaaSmrg    { PCI_CHIP_SAVAGE_IX,	"Savage/IX" },
186ab47cfaaSmrg    { PCI_CHIP_PROSAVAGE_PM,	"ProSavage PM133" },
187ab47cfaaSmrg    { PCI_CHIP_PROSAVAGE_KM,	"ProSavage KM133" },
188ab47cfaaSmrg    { PCI_CHIP_S3TWISTER_P,	"Twister PN133" },
189ab47cfaaSmrg    { PCI_CHIP_S3TWISTER_K,	"Twister KN133" },
190ab47cfaaSmrg    { PCI_CHIP_SUPSAV_MX128,	"SuperSavage/MX 128" },
191ab47cfaaSmrg    { PCI_CHIP_SUPSAV_MX64,	"SuperSavage/MX 64" },
192ab47cfaaSmrg    { PCI_CHIP_SUPSAV_MX64C,	"SuperSavage/MX 64C" },
193ab47cfaaSmrg    { PCI_CHIP_SUPSAV_IX128SDR,	"SuperSavage/IX 128" },
194ab47cfaaSmrg    { PCI_CHIP_SUPSAV_IX128DDR,	"SuperSavage/IX 128" },
195ab47cfaaSmrg    { PCI_CHIP_SUPSAV_IX64SDR,	"SuperSavage/IX 64" },
196ab47cfaaSmrg    { PCI_CHIP_SUPSAV_IX64DDR,	"SuperSavage/IX 64" },
197ab47cfaaSmrg    { PCI_CHIP_SUPSAV_IXCSDR,	"SuperSavage/IXC 64" },
198ab47cfaaSmrg    { PCI_CHIP_SUPSAV_IXCDDR,	"SuperSavage/IXC 64" },
199ab47cfaaSmrg    { PCI_CHIP_PROSAVAGE_DDR,	"ProSavage DDR" },
200ab47cfaaSmrg    { PCI_CHIP_PROSAVAGE_DDRK,	"ProSavage DDR-K" },
201ab47cfaaSmrg    { -1,			NULL }
202ab47cfaaSmrg};
203ab47cfaaSmrg
204ab47cfaaSmrgstatic SymTabRec SavageChipsets[] = {
205ab47cfaaSmrg    { S3_SAVAGE3D,	"Savage3D" },
206ab47cfaaSmrg    { S3_SAVAGE4,	"Savage4" },
207ab47cfaaSmrg    { S3_SAVAGE2000,	"Savage2000" },
208ab47cfaaSmrg    { S3_SAVAGE_MX,	"MobileSavage" },
209ab47cfaaSmrg    { S3_PROSAVAGE,	"ProSavage" },
210ab47cfaaSmrg    { S3_TWISTER,       "Twister"},
211ab47cfaaSmrg    { S3_PROSAVAGEDDR,  "ProSavageDDR"},
212ab47cfaaSmrg    { S3_SUPERSAVAGE,   "SuperSavage" },
213ab47cfaaSmrg    { -1,		NULL }
214ab47cfaaSmrg};
215ab47cfaaSmrg
2168697ee19Smrg#ifndef XSERVER_LIBPCIACCESS
217ab47cfaaSmrg/* This table maps a PCI device ID to a chipset family identifier. */
218ab47cfaaSmrg
219ab47cfaaSmrgstatic PciChipsets SavagePciChipsets[] = {
220ab47cfaaSmrg    { S3_SAVAGE3D,	PCI_CHIP_SAVAGE3D,	RES_SHARED_VGA },
221ab47cfaaSmrg    { S3_SAVAGE3D,	PCI_CHIP_SAVAGE3D_MV, 	RES_SHARED_VGA },
222ab47cfaaSmrg    { S3_SAVAGE4,	PCI_CHIP_SAVAGE4,	RES_SHARED_VGA },
223ab47cfaaSmrg    { S3_SAVAGE2000,	PCI_CHIP_SAVAGE2000,	RES_SHARED_VGA },
224ab47cfaaSmrg    { S3_SAVAGE_MX,	PCI_CHIP_SAVAGE_MX_MV,	RES_SHARED_VGA },
225ab47cfaaSmrg    { S3_SAVAGE_MX,	PCI_CHIP_SAVAGE_MX,	RES_SHARED_VGA },
226ab47cfaaSmrg    { S3_SAVAGE_MX,	PCI_CHIP_SAVAGE_IX_MV,	RES_SHARED_VGA },
227ab47cfaaSmrg    { S3_SAVAGE_MX,	PCI_CHIP_SAVAGE_IX,	RES_SHARED_VGA },
228ab47cfaaSmrg    { S3_PROSAVAGE,	PCI_CHIP_PROSAVAGE_PM,	RES_SHARED_VGA },
229ab47cfaaSmrg    { S3_PROSAVAGE,	PCI_CHIP_PROSAVAGE_KM,	RES_SHARED_VGA },
230ab47cfaaSmrg    { S3_TWISTER,	PCI_CHIP_S3TWISTER_P,	RES_SHARED_VGA },
231ab47cfaaSmrg    { S3_TWISTER,	PCI_CHIP_S3TWISTER_K,	RES_SHARED_VGA },
232ab47cfaaSmrg    { S3_PROSAVAGEDDR,	PCI_CHIP_PROSAVAGE_DDR,	RES_SHARED_VGA },
233ab47cfaaSmrg    { S3_PROSAVAGEDDR,	PCI_CHIP_PROSAVAGE_DDRK,	RES_SHARED_VGA },
234ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_MX128,	RES_SHARED_VGA },
235ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_MX64,	RES_SHARED_VGA },
236ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_MX64C,	RES_SHARED_VGA },
237ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_IX128SDR,	RES_SHARED_VGA },
238ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_IX128DDR,	RES_SHARED_VGA },
239ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_IX64SDR,	RES_SHARED_VGA },
240ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_IX64DDR,	RES_SHARED_VGA },
241ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_IXCSDR,	RES_SHARED_VGA },
242ab47cfaaSmrg    { S3_SUPERSAVAGE,	PCI_CHIP_SUPSAV_IXCDDR,	RES_SHARED_VGA },
243ab47cfaaSmrg    { -1,		-1,			RES_UNDEFINED }
244ab47cfaaSmrg};
2458697ee19Smrg#endif
246ab47cfaaSmrg
247ab47cfaaSmrgtypedef enum {
248ab47cfaaSmrg     OPTION_PCI_BURST
249ab47cfaaSmrg    ,OPTION_PCI_RETRY
250ab47cfaaSmrg    ,OPTION_NOACCEL
251ab47cfaaSmrg    ,OPTION_ACCELMETHOD
252ab47cfaaSmrg    ,OPTION_LCD_CENTER
253ab47cfaaSmrg    ,OPTION_LCDCLOCK
254ab47cfaaSmrg    ,OPTION_MCLK
255ab47cfaaSmrg    ,OPTION_REFCLK
256ab47cfaaSmrg    ,OPTION_SHOWCACHE
257ab47cfaaSmrg    ,OPTION_SWCURSOR
258ab47cfaaSmrg    ,OPTION_HWCURSOR
259ab47cfaaSmrg    ,OPTION_SHADOW_FB
260ab47cfaaSmrg    ,OPTION_ROTATE
261ab47cfaaSmrg    ,OPTION_USEBIOS
262ab47cfaaSmrg    ,OPTION_SHADOW_STATUS
263ab47cfaaSmrg    ,OPTION_CRT_ONLY
264ab47cfaaSmrg    ,OPTION_TV_ON
265ab47cfaaSmrg    ,OPTION_TV_PAL
266ab47cfaaSmrg    ,OPTION_FORCE_INIT
267ab47cfaaSmrg    ,OPTION_OVERLAY
268ab47cfaaSmrg    ,OPTION_T_KEY
269ab47cfaaSmrg    ,OPTION_DISABLE_XVMC
270ab47cfaaSmrg    ,OPTION_DISABLE_TILE
271ab47cfaaSmrg    ,OPTION_DISABLE_COB
272ab47cfaaSmrg    ,OPTION_BCI_FOR_XV
273ab47cfaaSmrg    ,OPTION_DVI
274ab47cfaaSmrg    ,OPTION_BUS_TYPE
275ab47cfaaSmrg    ,OPTION_DMA_TYPE
276ab47cfaaSmrg    ,OPTION_DMA_MODE
277ab47cfaaSmrg    ,OPTION_AGP_MODE
278ab47cfaaSmrg    ,OPTION_AGP_SIZE
279ab47cfaaSmrg    ,OPTION_DRI
2808697ee19Smrg    ,OPTION_IGNORE_EDID
281ab47cfaaSmrg} SavageOpts;
282ab47cfaaSmrg
283ab47cfaaSmrg
284ab47cfaaSmrgstatic const OptionInfoRec SavageOptions[] =
285ab47cfaaSmrg{
286ab47cfaaSmrg    { OPTION_NOACCEL,	"NoAccel",	OPTV_BOOLEAN, {0}, FALSE },
287ab47cfaaSmrg    { OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING,	{0}, FALSE },
288ab47cfaaSmrg    { OPTION_HWCURSOR,	"HWCursor",	OPTV_BOOLEAN, {0}, FALSE },
289ab47cfaaSmrg    { OPTION_SWCURSOR,	"SWCursor",	OPTV_BOOLEAN, {0}, FALSE },
290ab47cfaaSmrg    { OPTION_SHADOW_FB,	"ShadowFB",	OPTV_BOOLEAN, {0}, FALSE },
291ab47cfaaSmrg    { OPTION_ROTATE,	"Rotate",	OPTV_ANYSTR, {0}, FALSE },
292ab47cfaaSmrg    { OPTION_USEBIOS,	"UseBIOS",	OPTV_BOOLEAN, {0}, FALSE },
293ab47cfaaSmrg    { OPTION_LCDCLOCK,	"LCDClock",	OPTV_FREQ,    {0}, FALSE },
294ab47cfaaSmrg    { OPTION_SHADOW_STATUS, "ShadowStatus", OPTV_BOOLEAN, {0}, FALSE },
295ab47cfaaSmrg    { OPTION_CRT_ONLY,  "CrtOnly",      OPTV_BOOLEAN, {0}, FALSE },
296ab47cfaaSmrg    { OPTION_TV_ON,     "TvOn",         OPTV_BOOLEAN, {0}, FALSE },
297ab47cfaaSmrg    { OPTION_TV_PAL,    "PAL",          OPTV_BOOLEAN, {0}, FALSE },
298ab47cfaaSmrg    { OPTION_FORCE_INIT,"ForceInit",    OPTV_BOOLEAN, {0}, FALSE },
299ab47cfaaSmrg    { OPTION_OVERLAY,	"Overlay",	OPTV_ANYSTR, {0}, FALSE },
300ab47cfaaSmrg    { OPTION_T_KEY,	"TransparencyKey",	OPTV_ANYSTR, {0}, FALSE },
301ab47cfaaSmrg    { OPTION_FORCE_INIT,   "ForceInit",   OPTV_BOOLEAN, {0}, FALSE },
302ab47cfaaSmrg    { OPTION_DISABLE_XVMC, "DisableXVMC", OPTV_BOOLEAN, {0}, FALSE },
303ab47cfaaSmrg    { OPTION_DISABLE_TILE, "DisableTile", OPTV_BOOLEAN, {0}, FALSE },
304ab47cfaaSmrg    { OPTION_DISABLE_COB,  "DisableCOB",  OPTV_BOOLEAN, {0}, FALSE },
305ab47cfaaSmrg    { OPTION_BCI_FOR_XV,   "BCIforXv",    OPTV_BOOLEAN, {0}, FALSE },
306ab47cfaaSmrg    { OPTION_DVI,          "DVI",       OPTV_BOOLEAN, {0}, FALSE },
3078697ee19Smrg    { OPTION_IGNORE_EDID,  "IgnoreEDID",  OPTV_BOOLEAN, {0}, FALSE },
308ab47cfaaSmrg#ifdef XF86DRI
309ab47cfaaSmrg    { OPTION_BUS_TYPE,	"BusType",	OPTV_ANYSTR,  {0}, FALSE },
310ab47cfaaSmrg    { OPTION_DMA_TYPE,	"DmaType",	OPTV_ANYSTR,  {0}, FALSE },
311ab47cfaaSmrg    { OPTION_DMA_MODE,  "DmaMode",	OPTV_ANYSTR,  {0}, FALSE },
312ab47cfaaSmrg    { OPTION_AGP_MODE,	"AGPMode",	OPTV_INTEGER, {0}, FALSE },
313ab47cfaaSmrg    { OPTION_AGP_SIZE,	"AGPSize",	OPTV_INTEGER, {0}, FALSE },
314ab47cfaaSmrg    { OPTION_DRI,       "DRI",          OPTV_BOOLEAN, {0}, TRUE },
315ab47cfaaSmrg#endif
316ab47cfaaSmrg    { -1,		NULL,		OPTV_NONE,    {0}, FALSE }
317ab47cfaaSmrg};
318ab47cfaaSmrg
3198697ee19Smrg_X_EXPORT DriverRec SAVAGE =
3208697ee19Smrg{
3218697ee19Smrg    SAVAGE_VERSION,
3228697ee19Smrg    SAVAGE_DRIVER_NAME,
3238697ee19Smrg    SavageIdentify,
3248697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
3258697ee19Smrg    NULL,
3268697ee19Smrg#else
3278697ee19Smrg    SavageProbe,
3288697ee19Smrg#endif
3298697ee19Smrg    SavageAvailableOptions,
3308697ee19Smrg    NULL,
3318697ee19Smrg    0,
3328697ee19Smrg    NULL,
3338697ee19Smrg
3348697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
3358697ee19Smrg    savage_device_match,
3368697ee19Smrg    SavagePciProbe
3378697ee19Smrg#endif
3388697ee19Smrg};
3398697ee19Smrg
3408697ee19Smrg
341ab47cfaaSmrg
342ab47cfaaSmrgstatic const char *vgaHWSymbols[] = {
343ab47cfaaSmrg    "vgaHWBlankScreen",
344ab47cfaaSmrg    "vgaHWCopyReg",
345ab47cfaaSmrg    "vgaHWGetHWRec",
346ab47cfaaSmrg    "vgaHWGetIOBase",
347ab47cfaaSmrg    "vgaHWGetIndex",
348ab47cfaaSmrg    "vgaHWInit",
349ab47cfaaSmrg    "vgaHWLock",
350ab47cfaaSmrg    "vgaHWProtect",
351ab47cfaaSmrg    "vgaHWRestore",
352ab47cfaaSmrg    "vgaHWSave",
353ab47cfaaSmrg    "vgaHWSaveScreen",
354ab47cfaaSmrg    "vgaHWSetMmioFuncs",
355ab47cfaaSmrg    "vgaHWSetStdFuncs",
356ab47cfaaSmrg    "vgaHWUnmapMem",
357ab47cfaaSmrg    "vgaHWddc1SetSpeedWeak",
358ab47cfaaSmrg#if 0
359ab47cfaaSmrg    "vgaHWFreeHWRec",
360ab47cfaaSmrg    "vgaHWMapMem",
361ab47cfaaSmrg    "vgaHWUnlock",
362ab47cfaaSmrg#endif
363ab47cfaaSmrg    NULL
364ab47cfaaSmrg};
365ab47cfaaSmrg
366ab47cfaaSmrg#ifdef XF86DRI
367ab47cfaaSmrgstatic const char *drmSymbols[] = {
368ab47cfaaSmrg    "drmAvailable",
369ab47cfaaSmrg    "drmAddBufs",
370ab47cfaaSmrg    "drmAddMap",
371ab47cfaaSmrg    "drmCtlInstHandler",
372ab47cfaaSmrg    "drmGetInterruptFromBusID",
373ab47cfaaSmrg    "drmFreeVersion",
374ab47cfaaSmrg    "drmGetVersion",
375ab47cfaaSmrg    "drmMap",
376ab47cfaaSmrg    "drmUnmap",
377ab47cfaaSmrg    "drmMapBufs",
378ab47cfaaSmrg    "drmUnmapBufs",
379ab47cfaaSmrg    "drmAgpAcquire",
380ab47cfaaSmrg    "drmAgpRelease",
381ab47cfaaSmrg    "drmAgpEnable",
382ab47cfaaSmrg    "drmAgpAlloc",
383ab47cfaaSmrg    "drmAgpFree",
384ab47cfaaSmrg    "drmAgpBind",
385ab47cfaaSmrg    "drmAgpUnbind",
386ab47cfaaSmrg    "drmAgpGetMode",
387ab47cfaaSmrg    "drmAgpBase",
388ab47cfaaSmrg    "drmAgpSize",
389ab47cfaaSmrg    "drmAgpVendorId",
390ab47cfaaSmrg    "drmAgpDeviceId",
391ab47cfaaSmrg    "drmMGAInitDMA",
392ab47cfaaSmrg    "drmMGACleanupDMA",
393ab47cfaaSmrg    "drmMGAFlushDMA",
394ab47cfaaSmrg    "drmMGAEngineReset",
395ab47cfaaSmrg    NULL
396ab47cfaaSmrg};
397ab47cfaaSmrg
398ab47cfaaSmrgstatic const char *driSymbols[] = {
399ab47cfaaSmrg    "DRIGetDrawableIndex",
400ab47cfaaSmrg    "DRIFinishScreenInit",
401ab47cfaaSmrg    "DRIDestroyInfoRec",
402ab47cfaaSmrg    "DRICloseScreen",
403ab47cfaaSmrg    "DRIDestroyInfoRec",
404ab47cfaaSmrg    "DRIScreenInit",
405ab47cfaaSmrg    "DRIDestroyInfoRec",
406ab47cfaaSmrg    "DRICreateInfoRec",
407ab47cfaaSmrg    "DRILock",
408ab47cfaaSmrg    "DRIUnlock",
409ab47cfaaSmrg    "DRIGetSAREAPrivate",
410ab47cfaaSmrg    "DRIGetContext",
411ab47cfaaSmrg    "DRIQueryVersion",
412ab47cfaaSmrg    "DRIAdjustFrame",
413ab47cfaaSmrg    "DRIOpenFullScreen",
414ab47cfaaSmrg    "DRICloseFullScreen",
415ab47cfaaSmrg    "GlxSetVisualConfigs",
416ab47cfaaSmrg    NULL
417ab47cfaaSmrg};
418ab47cfaaSmrg#endif
419ab47cfaaSmrg
420ab47cfaaSmrg
421ab47cfaaSmrgstatic const char *ramdacSymbols[] = {
422ab47cfaaSmrg    "xf86CreateCursorInfoRec",
423ab47cfaaSmrg#if 0
424ab47cfaaSmrg    "xf86DestroyCursorInfoRec",
425ab47cfaaSmrg#endif
426ab47cfaaSmrg    "xf86InitCursor",
427ab47cfaaSmrg    NULL
428ab47cfaaSmrg};
429ab47cfaaSmrg
430ab47cfaaSmrgstatic const char *int10Symbols[] = {
431ab47cfaaSmrg    "xf86ExecX86int10",
432ab47cfaaSmrg    "xf86Int10AllocPages",
433ab47cfaaSmrg    "xf86int10Addr",
434ab47cfaaSmrg    "xf86Int10FreePages"
435ab47cfaaSmrg};
436ab47cfaaSmrg
437ab47cfaaSmrgstatic const char *vbeSymbols[] = {
438ab47cfaaSmrg    "VBEInit",
439ab47cfaaSmrg    "vbeDoEDID",
440ab47cfaaSmrg#if 0
441ab47cfaaSmrg    "vbeFree",
442ab47cfaaSmrg#endif
443ab47cfaaSmrg    NULL
444ab47cfaaSmrg};
445ab47cfaaSmrg
446ab47cfaaSmrgstatic const char *vbeOptSymbols[] = {
447ab47cfaaSmrg    "vbeModeInit",
448ab47cfaaSmrg    "VBESetVBEMode",
449ab47cfaaSmrg    "VBEGetVBEInfo",
450ab47cfaaSmrg    "VBEFreeVBEInfo",
451ab47cfaaSmrg    NULL
452ab47cfaaSmrg};
453ab47cfaaSmrg
454ab47cfaaSmrgstatic const char *ddcSymbols[] = {
455ab47cfaaSmrg    "xf86DoEDID_DDC1",
456ab47cfaaSmrg    "xf86DoEDID_DDC2",
457ab47cfaaSmrg    "xf86PrintEDID",
458ab47cfaaSmrg    "xf86SetDDCproperties",
459ab47cfaaSmrg    NULL
460ab47cfaaSmrg};
461ab47cfaaSmrg
462ab47cfaaSmrgstatic const char *i2cSymbols[] = {
463ab47cfaaSmrg    "xf86CreateI2CBusRec",
464ab47cfaaSmrg    "xf86I2CBusInit",
465ab47cfaaSmrg    "xf86CreateI2CDevRec",
466ab47cfaaSmrg    "xf86I2CDevInit",
467ab47cfaaSmrg    "xf86I2CWriteByte",
468ab47cfaaSmrg    "xf86I2CWriteBytes",
469ab47cfaaSmrg    "xf86I2CReadByte",
470ab47cfaaSmrg    "xf86I2CReadBytes",
471ab47cfaaSmrg    "xf86I2CWriteRead",
472ab47cfaaSmrg    "xf86DestroyI2CDevRec",
473ab47cfaaSmrg    NULL
474ab47cfaaSmrg};
475ab47cfaaSmrg
476ab47cfaaSmrgstatic const char *xaaSymbols[] = {
477ab47cfaaSmrg    "XAAGetCopyROP",
478ab47cfaaSmrg    "XAAGetCopyROP_PM",
479ab47cfaaSmrg    "XAACreateInfoRec",
480ab47cfaaSmrg    "XAADestroyInfoRec",
481ab47cfaaSmrg    "XAAFillSolidRects",
482ab47cfaaSmrg    "XAAHelpPatternROP",
483ab47cfaaSmrg    "XAAHelpSolidROP",
484ab47cfaaSmrg    "XAAInit",
485ab47cfaaSmrg    "XAAScreenIndex",
486ab47cfaaSmrg    NULL
487ab47cfaaSmrg};
488ab47cfaaSmrg
489ab47cfaaSmrgstatic const char *exaSymbols[] = {
490ab47cfaaSmrg    "exaDriverAlloc",
491ab47cfaaSmrg    "exaDriverInit",
492ab47cfaaSmrg    "exaDriverFini",
493ab47cfaaSmrg    "exaOffscreenAlloc",
494ab47cfaaSmrg    "exaOffscreenFree",
495ab47cfaaSmrg    "exaGetPixmapOffset",
496ab47cfaaSmrg    "exaGetPixmapPitch",
497ab47cfaaSmrg    "exaGetPixmapSize",
498ab47cfaaSmrg    NULL
499ab47cfaaSmrg};
500ab47cfaaSmrg
501ab47cfaaSmrgstatic const char *shadowSymbols[] = {
502ab47cfaaSmrg    "ShadowFBInit",
503ab47cfaaSmrg    NULL
504ab47cfaaSmrg};
505ab47cfaaSmrg
506ab47cfaaSmrgstatic const char *fbSymbols[] = {
507ab47cfaaSmrg    "fbPictureInit",
508ab47cfaaSmrg    "fbScreenInit",
509ab47cfaaSmrg    NULL
510ab47cfaaSmrg};
511ab47cfaaSmrg
512ab47cfaaSmrg#ifdef XFree86LOADER
513ab47cfaaSmrg
514ab47cfaaSmrgstatic MODULESETUPPROTO(SavageSetup);
515ab47cfaaSmrg
516ab47cfaaSmrgstatic XF86ModuleVersionInfo SavageVersRec = {
517ab47cfaaSmrg    "savage",
518ab47cfaaSmrg    MODULEVENDORSTRING,
519ab47cfaaSmrg    MODINFOSTRING1,
520ab47cfaaSmrg    MODINFOSTRING2,
521ab47cfaaSmrg    XORG_VERSION_CURRENT,
522ab47cfaaSmrg    SAVAGE_VERSION_MAJOR, SAVAGE_VERSION_MINOR, SAVAGE_PATCHLEVEL,
523ab47cfaaSmrg    ABI_CLASS_VIDEODRV,
524ab47cfaaSmrg    ABI_VIDEODRV_VERSION,
525ab47cfaaSmrg    MOD_CLASS_VIDEODRV,
526ab47cfaaSmrg    {0, 0, 0, 0}
527ab47cfaaSmrg};
528ab47cfaaSmrg
529ab47cfaaSmrg_X_EXPORT XF86ModuleData savageModuleData = {
530ab47cfaaSmrg    &SavageVersRec,
531ab47cfaaSmrg    SavageSetup,
532ab47cfaaSmrg    NULL
533ab47cfaaSmrg};
534ab47cfaaSmrg
535ab47cfaaSmrgstatic pointer SavageSetup(pointer module, pointer opts, int *errmaj,
536ab47cfaaSmrg			   int *errmin)
537ab47cfaaSmrg{
538ab47cfaaSmrg    static Bool setupDone = FALSE;
539ab47cfaaSmrg
540ab47cfaaSmrg    if (!setupDone) {
541ab47cfaaSmrg	setupDone = TRUE;
542ab47cfaaSmrg	xf86AddDriver(&SAVAGE, module, 1);
543ab47cfaaSmrg	LoaderRefSymLists(vgaHWSymbols, fbSymbols, ramdacSymbols,
544ab47cfaaSmrg			  xaaSymbols,
545ab47cfaaSmrg			  exaSymbols,
546ab47cfaaSmrg			  shadowSymbols, vbeSymbols, vbeOptSymbols,
547ab47cfaaSmrg#ifdef XF86DRI
548ab47cfaaSmrg                          drmSymbols, driSymbols,
549ab47cfaaSmrg#endif
550ab47cfaaSmrg			  int10Symbols, i2cSymbols, ddcSymbols, NULL);
551ab47cfaaSmrg	return (pointer) 1;
552ab47cfaaSmrg    } else {
553ab47cfaaSmrg	if (errmaj)
554ab47cfaaSmrg	    *errmaj = LDR_ONCEONLY;
555ab47cfaaSmrg	return NULL;
556ab47cfaaSmrg    }
557ab47cfaaSmrg}
558ab47cfaaSmrg
559ab47cfaaSmrg#endif /* XFree86LOADER */
560ab47cfaaSmrg
561ab47cfaaSmrgstatic SavageEntPtr SavageEntPriv(ScrnInfoPtr pScrn)
562ab47cfaaSmrg{
563ab47cfaaSmrg    DevUnion     *pPriv;
564ab47cfaaSmrg    SavagePtr  psav   = SAVPTR(pScrn);
565ab47cfaaSmrg    pPriv = xf86GetEntityPrivate(psav->pEnt->index,
566ab47cfaaSmrg                                 gSavageEntityIndex);
567ab47cfaaSmrg    return pPriv->ptr;
568ab47cfaaSmrg}
569ab47cfaaSmrg
570ab47cfaaSmrg
571ab47cfaaSmrg/*
572ab47cfaaSmrg * I'd rather have these wait macros be inline, but S3 has made it
573ab47cfaaSmrg * darned near impossible.  The bit fields are in a different place in
574ab47cfaaSmrg * all three families, the status register has a different address in the
575ab47cfaaSmrg * three families, and even the idle vs busy sense flipped in the Sav2K.
576ab47cfaaSmrg */
577ab47cfaaSmrg
578ab47cfaaSmrgstatic void
579ab47cfaaSmrgResetBCI2K( SavagePtr psav )
580ab47cfaaSmrg{
581ab47cfaaSmrg    CARD32 cob = INREG( 0x48c18 );
582ab47cfaaSmrg    /* if BCI is enabled and BCI is busy... */
583ab47cfaaSmrg
584ab47cfaaSmrg    if(
585ab47cfaaSmrg	(cob & 0x00000008) &&
586ab47cfaaSmrg	! (ALT_STATUS_WORD0 & 0x00200000)
587ab47cfaaSmrg    )
588ab47cfaaSmrg    {
589ab47cfaaSmrg	ErrorF( "Resetting BCI, stat = %08lx...\n",
590ab47cfaaSmrg		(unsigned long) ALT_STATUS_WORD0);
591ab47cfaaSmrg	/* Turn off BCI */
592ab47cfaaSmrg	OUTREG( 0x48c18, cob & ~8 );
593ab47cfaaSmrg	usleep(10000);
594ab47cfaaSmrg	/* Turn it back on */
595ab47cfaaSmrg	OUTREG( 0x48c18, cob );
596ab47cfaaSmrg	usleep(10000);
597ab47cfaaSmrg    }
598ab47cfaaSmrg}
599ab47cfaaSmrg
600ab47cfaaSmrgstatic Bool
601ab47cfaaSmrgShadowWait( SavagePtr psav )
602ab47cfaaSmrg{
603ab47cfaaSmrg    BCI_GET_PTR;
604ab47cfaaSmrg    int loop = 0;
605ab47cfaaSmrg
606ab47cfaaSmrg    if( !psav->NoPCIRetry )
607ab47cfaaSmrg	return 0;
608ab47cfaaSmrg
609ab47cfaaSmrg    psav->ShadowCounter = (psav->ShadowCounter + 1) & 0xffff;
610ab47cfaaSmrg    if (psav->ShadowCounter == 0)
611ab47cfaaSmrg	psav->ShadowCounter++; /* 0 is reserved for the BIOS
612ab47cfaaSmrg				  to avoid confusion in the DRM */
613ab47cfaaSmrg    BCI_SEND( psav->dwBCIWait2DIdle );
614ab47cfaaSmrg    BCI_SEND( 0x98000000 + psav->ShadowCounter );
615ab47cfaaSmrg
616ab47cfaaSmrg    while(
617ab47cfaaSmrg	(int)(psav->ShadowVirtual[psav->eventStatusReg] & 0xffff) !=
618ab47cfaaSmrg	psav->ShadowCounter && (loop++ < MAXLOOP)
619ab47cfaaSmrg    )
620ab47cfaaSmrg	;
621ab47cfaaSmrg
622ab47cfaaSmrg    return loop >= MAXLOOP;
623ab47cfaaSmrg}
624ab47cfaaSmrg
625ab47cfaaSmrgstatic Bool
626ab47cfaaSmrgShadowWaitQueue( SavagePtr psav, int v )
627ab47cfaaSmrg{
628ab47cfaaSmrg    int loop = 0;
629ab47cfaaSmrg    CARD32 slots = MAXFIFO - v;
630ab47cfaaSmrg
631ab47cfaaSmrg    if (slots >= psav->bciThresholdHi)
632ab47cfaaSmrg	slots = psav->bciThresholdHi;
633ab47cfaaSmrg    else
634ab47cfaaSmrg	return ShadowWait( psav );
635ab47cfaaSmrg
636ab47cfaaSmrg    /* Savage 2000 reports only entries filled in the COB, not the on-chip
637ab47cfaaSmrg     * queue. Also it reports in qword units instead of dwords. */
638ab47cfaaSmrg    if (psav->Chipset == S3_SAVAGE2000)
639ab47cfaaSmrg	slots = (slots - 32) / 4;
640ab47cfaaSmrg
641ab47cfaaSmrg    while( ((psav->ShadowVirtual[0] & psav->bciUsedMask) >= slots) && (loop++ < MAXLOOP))
642ab47cfaaSmrg	;
643ab47cfaaSmrg
644ab47cfaaSmrg    return loop >= MAXLOOP;
645ab47cfaaSmrg}
646ab47cfaaSmrg
647ab47cfaaSmrg/* Wait until "v" queue entries are free */
648ab47cfaaSmrg
649ab47cfaaSmrgstatic int
650ab47cfaaSmrgWaitQueue3D( SavagePtr psav, int v )
651ab47cfaaSmrg{
652ab47cfaaSmrg    int loop = 0;
653ab47cfaaSmrg    CARD32 slots = MAXFIFO - v;
654ab47cfaaSmrg
655ab47cfaaSmrg    mem_barrier();
656ab47cfaaSmrg    if( psav->ShadowVirtual )
657ab47cfaaSmrg    {
658ab47cfaaSmrg	psav->WaitQueue = ShadowWaitQueue;
659ab47cfaaSmrg	return ShadowWaitQueue(psav, v);
660ab47cfaaSmrg    }
661ab47cfaaSmrg    else
662ab47cfaaSmrg    {
663ab47cfaaSmrg	loop &= STATUS_WORD0;
664ab47cfaaSmrg	while( ((STATUS_WORD0 & 0x0000ffff) > slots) && (loop++ < MAXLOOP))
665ab47cfaaSmrg	    ;
666ab47cfaaSmrg    }
667ab47cfaaSmrg    return loop >= MAXLOOP;
668ab47cfaaSmrg}
669ab47cfaaSmrg
670ab47cfaaSmrgstatic int
671ab47cfaaSmrgWaitQueue4( SavagePtr psav, int v )
672ab47cfaaSmrg{
673ab47cfaaSmrg    int loop = 0;
674ab47cfaaSmrg    CARD32 slots = MAXFIFO - v;
675ab47cfaaSmrg
676ab47cfaaSmrg    if( !psav->NoPCIRetry )
677ab47cfaaSmrg	return 0;
678ab47cfaaSmrg    mem_barrier();
679ab47cfaaSmrg    if( psav->ShadowVirtual )
680ab47cfaaSmrg    {
681ab47cfaaSmrg	psav->WaitQueue = ShadowWaitQueue;
682ab47cfaaSmrg	return ShadowWaitQueue(psav, v);
683ab47cfaaSmrg    }
684ab47cfaaSmrg    else
685ab47cfaaSmrg	while( ((ALT_STATUS_WORD0 & 0x001fffff) > slots) && (loop++ < MAXLOOP));
686ab47cfaaSmrg    return loop >= MAXLOOP;
687ab47cfaaSmrg}
688ab47cfaaSmrg
689ab47cfaaSmrgstatic int
690ab47cfaaSmrgWaitQueue2K( SavagePtr psav, int v )
691ab47cfaaSmrg{
692ab47cfaaSmrg    int loop = 0;
693ab47cfaaSmrg    CARD32 slots = (MAXFIFO - v) / 4;
694ab47cfaaSmrg
695ab47cfaaSmrg    if( !psav->NoPCIRetry )
696ab47cfaaSmrg	return 0;
697ab47cfaaSmrg    mem_barrier();
698ab47cfaaSmrg    if( psav->ShadowVirtual )
699ab47cfaaSmrg    {
700ab47cfaaSmrg	psav->WaitQueue = ShadowWaitQueue;
701ab47cfaaSmrg	return ShadowWaitQueue(psav, v);
702ab47cfaaSmrg    }
703ab47cfaaSmrg    else
704ab47cfaaSmrg	while( ((ALT_STATUS_WORD0 & 0x000fffff) > slots) && (loop++ < MAXLOOP))
705ab47cfaaSmrg	    ;
706ab47cfaaSmrg    if( loop >= MAXLOOP )
707ab47cfaaSmrg	ResetBCI2K(psav);
708ab47cfaaSmrg    return loop >= MAXLOOP;
709ab47cfaaSmrg}
710ab47cfaaSmrg
711ab47cfaaSmrg/* Wait until GP is idle and queue is empty */
712ab47cfaaSmrg
713ab47cfaaSmrgstatic int
714ab47cfaaSmrgWaitIdleEmpty3D(SavagePtr psav)
715ab47cfaaSmrg{
716ab47cfaaSmrg    int loop = 0;
717ab47cfaaSmrg    mem_barrier();
718ab47cfaaSmrg    if( psav->ShadowVirtual )
719ab47cfaaSmrg    {
720ab47cfaaSmrg	psav->WaitIdleEmpty = ShadowWait;
721ab47cfaaSmrg	return ShadowWait(psav);
722ab47cfaaSmrg    }
723ab47cfaaSmrg    loop &= STATUS_WORD0;
724ab47cfaaSmrg    while( ((STATUS_WORD0 & 0x0008ffff) != 0x80000) && (loop++ < MAXLOOP) );
725ab47cfaaSmrg    return loop >= MAXLOOP;
726ab47cfaaSmrg}
727ab47cfaaSmrg
728ab47cfaaSmrgstatic int
729ab47cfaaSmrgWaitIdleEmpty4(SavagePtr psav)
730ab47cfaaSmrg{
731ab47cfaaSmrg    int loop = 0;
732ab47cfaaSmrg    mem_barrier();
733ab47cfaaSmrg    if( psav->ShadowVirtual )
734ab47cfaaSmrg    {
735ab47cfaaSmrg	psav->WaitIdleEmpty = ShadowWait;
736ab47cfaaSmrg	return ShadowWait(psav);
737ab47cfaaSmrg    }
738ab47cfaaSmrg	/* which is right?*/
739ab47cfaaSmrg    /*while( ((ALT_STATUS_WORD0 & 0x00a1ffff) != 0x00a00000) && (loop++ < MAXLOOP) );*/ /* tim */
740ab47cfaaSmrg    while (((ALT_STATUS_WORD0 & 0x00e1ffff) != 0x00e00000) && (loop++ < MAXLOOP)); /* S3 */
741ab47cfaaSmrg    return loop >= MAXLOOP;
742ab47cfaaSmrg}
743ab47cfaaSmrg
744ab47cfaaSmrgstatic int
745ab47cfaaSmrgWaitIdleEmpty2K(SavagePtr psav)
746ab47cfaaSmrg{
747ab47cfaaSmrg    int loop = 0;
748ab47cfaaSmrg    mem_barrier();
749ab47cfaaSmrg    if( psav->ShadowVirtual )
750ab47cfaaSmrg    {
751ab47cfaaSmrg	psav->WaitIdleEmpty = ShadowWait;
752ab47cfaaSmrg	return ShadowWait(psav);
753ab47cfaaSmrg    }
754ab47cfaaSmrg    loop &= ALT_STATUS_WORD0;
755ab47cfaaSmrg    while( ((ALT_STATUS_WORD0 & 0x009fffff) != 0) && (loop++ < MAXLOOP) );
756ab47cfaaSmrg    if( loop >= MAXLOOP )
757ab47cfaaSmrg	ResetBCI2K(psav);
758ab47cfaaSmrg    return loop >= MAXLOOP;
759ab47cfaaSmrg}
760ab47cfaaSmrg
761ab47cfaaSmrg/* Wait until GP is idle */
762ab47cfaaSmrg
763ab47cfaaSmrgstatic int
764ab47cfaaSmrgWaitIdle3D(SavagePtr psav)
765ab47cfaaSmrg{
766ab47cfaaSmrg    int loop = 0;
767ab47cfaaSmrg    mem_barrier();
768ab47cfaaSmrg    if( psav->ShadowVirtual )
769ab47cfaaSmrg    {
770ab47cfaaSmrg	psav->WaitIdle = ShadowWait;
771ab47cfaaSmrg	return ShadowWait(psav);
772ab47cfaaSmrg    }
773ab47cfaaSmrg    while( (!(STATUS_WORD0 & 0x00080000)) && (loop++ < MAXLOOP) );
774ab47cfaaSmrg    return loop >= MAXLOOP;
775ab47cfaaSmrg}
776ab47cfaaSmrg
777ab47cfaaSmrgstatic int
778ab47cfaaSmrgWaitIdle4(SavagePtr psav)
779ab47cfaaSmrg{
780ab47cfaaSmrg    int loop = 0;
781ab47cfaaSmrg    mem_barrier();
782ab47cfaaSmrg    if( psav->ShadowVirtual )
783ab47cfaaSmrg    {
784ab47cfaaSmrg	psav->WaitIdle = ShadowWait;
785ab47cfaaSmrg	return ShadowWait(psav);
786ab47cfaaSmrg    }
787ab47cfaaSmrg	/* which is right?*/
788ab47cfaaSmrg    /*while( (!(ALT_STATUS_WORD0 & 0x00800000)) && (loop++ < MAXLOOP) );*/ /* tim */
789ab47cfaaSmrg    while (((ALT_STATUS_WORD0 & 0x00E00000)!=0x00E00000) && (loop++ < MAXLOOP)); /* S3 */
790ab47cfaaSmrg    return loop >= MAXLOOP;
791ab47cfaaSmrg}
792ab47cfaaSmrg
793ab47cfaaSmrgstatic int
794ab47cfaaSmrgWaitIdle2K(SavagePtr psav)
795ab47cfaaSmrg{
796ab47cfaaSmrg    int loop = 0;
797ab47cfaaSmrg    mem_barrier();
798ab47cfaaSmrg    if( psav->ShadowVirtual )
799ab47cfaaSmrg    {
800ab47cfaaSmrg	psav->WaitIdle = ShadowWait;
801ab47cfaaSmrg	return ShadowWait(psav);
802ab47cfaaSmrg    }
803ab47cfaaSmrg    loop &= ALT_STATUS_WORD0;
804ab47cfaaSmrg    while( (ALT_STATUS_WORD0 & 0x00900000) && (loop++ < MAXLOOP) );
805ab47cfaaSmrg    return loop >= MAXLOOP;
806ab47cfaaSmrg}
807ab47cfaaSmrg
808ab47cfaaSmrg
809ab47cfaaSmrgstatic Bool SavageGetRec(ScrnInfoPtr pScrn)
810ab47cfaaSmrg{
811ab47cfaaSmrg    if (pScrn->driverPrivate)
812ab47cfaaSmrg	return TRUE;
813ab47cfaaSmrg
814ab47cfaaSmrg    pScrn->driverPrivate = xnfcalloc(sizeof(SavageRec), 1);
815ab47cfaaSmrg    return TRUE;
816ab47cfaaSmrg}
817ab47cfaaSmrg
818ab47cfaaSmrg
819ab47cfaaSmrgstatic void SavageFreeRec(ScrnInfoPtr pScrn)
820ab47cfaaSmrg{
821ab47cfaaSmrg    TRACE(( "SavageFreeRec(%x)\n", pScrn->driverPrivate ));
822ab47cfaaSmrg    if (!pScrn->driverPrivate)
823ab47cfaaSmrg	return;
824ab47cfaaSmrg    SavageUnmapMem(pScrn, 1);
825ab47cfaaSmrg    xfree(pScrn->driverPrivate);
826ab47cfaaSmrg    pScrn->driverPrivate = NULL;
827ab47cfaaSmrg}
828ab47cfaaSmrg
829ab47cfaaSmrg
830ab47cfaaSmrgstatic const OptionInfoRec * SavageAvailableOptions(int chipid, int busid)
831ab47cfaaSmrg{
832ab47cfaaSmrg    return SavageOptions;
833ab47cfaaSmrg}
834ab47cfaaSmrg
835ab47cfaaSmrg
836ab47cfaaSmrgstatic void SavageIdentify(int flags)
837ab47cfaaSmrg{
838ab47cfaaSmrg    xf86PrintChipsets("SAVAGE",
839ab47cfaaSmrg		      "driver (version " SAVAGE_DRIVER_VERSION ") for S3 Savage chipsets",
840ab47cfaaSmrg		      SavageChips);
841ab47cfaaSmrg}
842ab47cfaaSmrg
843ab47cfaaSmrg
8448697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
8458697ee19Smrgstatic Bool SavagePciProbe(DriverPtr drv, int entity_num,
8468697ee19Smrg			   struct pci_device *dev, intptr_t match_data)
8478697ee19Smrg{
8488697ee19Smrg    ScrnInfoPtr pScrn;
8498697ee19Smrg
8508697ee19Smrg
8518697ee19Smrg    if ((match_data < S3_SAVAGE3D) || (match_data > S3_SAVAGE2000)) {
8528697ee19Smrg 	return FALSE;
8538697ee19Smrg    }
8548697ee19Smrg
8558697ee19Smrg    pScrn = xf86ConfigPciEntity(NULL, 0, entity_num, NULL,
8568697ee19Smrg				RES_SHARED_VGA, NULL, NULL, NULL, NULL);
8578697ee19Smrg    if (pScrn != NULL) {
8588697ee19Smrg	EntityInfoPtr pEnt;
8598697ee19Smrg	SavagePtr psav;
8608697ee19Smrg
8618697ee19Smrg
8628697ee19Smrg	pScrn->driverVersion = SAVAGE_VERSION;
8638697ee19Smrg	pScrn->driverName = SAVAGE_DRIVER_NAME;
8648697ee19Smrg	pScrn->name = "SAVAGE";
8658697ee19Smrg	pScrn->Probe = NULL;
8668697ee19Smrg	pScrn->PreInit = SavagePreInit;
8678697ee19Smrg	pScrn->ScreenInit = SavageScreenInit;
8688697ee19Smrg	pScrn->SwitchMode = SavageSwitchMode;
8698697ee19Smrg	pScrn->AdjustFrame = SavageAdjustFrame;
8708697ee19Smrg	pScrn->EnterVT = SavageEnterVT;
8718697ee19Smrg	pScrn->LeaveVT = SavageLeaveVT;
8728697ee19Smrg	pScrn->FreeScreen = NULL;
8738697ee19Smrg	pScrn->ValidMode = SavageValidMode;
8748697ee19Smrg
8758697ee19Smrg	if (!SavageGetRec(pScrn))
8768697ee19Smrg	    return FALSE;
8778697ee19Smrg
8788697ee19Smrg	psav = SAVPTR(pScrn);
8798697ee19Smrg
8808697ee19Smrg	psav->PciInfo = dev;
8818697ee19Smrg	psav->Chipset = match_data;
8828697ee19Smrg
8838697ee19Smrg	pEnt = xf86GetEntityInfo(entity_num);
8848697ee19Smrg
8858697ee19Smrg	/* MX, IX, SuperSavage cards support Dual-Head, mark the entity as
8868697ee19Smrg	 * sharable.
8878697ee19Smrg	 */
8888697ee19Smrg	if (pEnt->chipset == S3_SAVAGE_MX || pEnt->chipset == S3_SUPERSAVAGE) {
8898697ee19Smrg	    DevUnion   *pPriv;
8908697ee19Smrg	    SavageEntPtr pSavageEnt;
8918697ee19Smrg
8928697ee19Smrg	    xf86SetEntitySharable(entity_num);
8938697ee19Smrg
8948697ee19Smrg	    if (gSavageEntityIndex == -1)
8958697ee19Smrg	        gSavageEntityIndex = xf86AllocateEntityPrivateIndex();
8968697ee19Smrg
8978697ee19Smrg	    pPriv = xf86GetEntityPrivate(pEnt->index, gSavageEntityIndex);
8988697ee19Smrg	    if (!pPriv->ptr) {
8998697ee19Smrg		int j;
9008697ee19Smrg		int instance = xf86GetNumEntityInstances(pEnt->index);
9018697ee19Smrg
9028697ee19Smrg		for (j = 0; j < instance; j++)
9038697ee19Smrg		    xf86SetEntityInstanceForScreen(pScrn, pEnt->index, j);
9048697ee19Smrg
9058697ee19Smrg		pPriv->ptr = xnfcalloc(sizeof(SavageEntRec), 1);
9068697ee19Smrg		pSavageEnt = pPriv->ptr;
9078697ee19Smrg		pSavageEnt->HasSecondary = FALSE;
9088697ee19Smrg	    } else {
9098697ee19Smrg		pSavageEnt = pPriv->ptr;
9108697ee19Smrg		pSavageEnt->HasSecondary = TRUE;
9118697ee19Smrg	    }
9128697ee19Smrg	}
9138697ee19Smrg    }
9148697ee19Smrg
9158697ee19Smrg    return (pScrn != NULL);
9168697ee19Smrg}
9178697ee19Smrg
9188697ee19Smrg#else
9198697ee19Smrg
920ab47cfaaSmrgstatic Bool SavageProbe(DriverPtr drv, int flags)
921ab47cfaaSmrg{
922ab47cfaaSmrg    int i;
923ab47cfaaSmrg    GDevPtr *devSections = NULL;
924ab47cfaaSmrg    int *usedChips;
925ab47cfaaSmrg    int numDevSections;
926ab47cfaaSmrg    int numUsed;
927ab47cfaaSmrg    Bool foundScreen = FALSE;
928ab47cfaaSmrg
929ab47cfaaSmrg    /* sanity checks */
930ab47cfaaSmrg    if ((numDevSections = xf86MatchDevice("savage", &devSections)) <= 0)
931ab47cfaaSmrg	return FALSE;
932ab47cfaaSmrg    if (xf86GetPciVideoInfo() == NULL) {
933ab47cfaaSmrg        if (devSections)
934ab47cfaaSmrg	    xfree(devSections);
935ab47cfaaSmrg        return FALSE;
936ab47cfaaSmrg    }
937ab47cfaaSmrg
938ab47cfaaSmrg    numUsed = xf86MatchPciInstances("SAVAGE", PCI_VENDOR_S3,
939ab47cfaaSmrg				    SavageChipsets, SavagePciChipsets,
940ab47cfaaSmrg				    devSections, numDevSections, drv,
941ab47cfaaSmrg				    &usedChips);
942ab47cfaaSmrg    if (devSections)
943ab47cfaaSmrg	xfree(devSections);
944ab47cfaaSmrg    devSections = NULL;
945ab47cfaaSmrg    if (numUsed <= 0)
946ab47cfaaSmrg	return FALSE;
947ab47cfaaSmrg
948ab47cfaaSmrg    if (flags & PROBE_DETECT)
949ab47cfaaSmrg	foundScreen = TRUE;
950ab47cfaaSmrg    else
951ab47cfaaSmrg	for (i=0; i<numUsed; i++) {
952ab47cfaaSmrg            EntityInfoPtr pEnt = xf86GetEntityInfo(usedChips[i]);;
953ab47cfaaSmrg            ScrnInfoPtr pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
954ab47cfaaSmrg						    NULL, RES_SHARED_VGA,
955ab47cfaaSmrg						    NULL, NULL, NULL, NULL);
956ab47cfaaSmrg
957ab47cfaaSmrg            if (pScrn != NULL) {
9588697ee19Smrg		SavagePtr psav;
9598697ee19Smrg
960ab47cfaaSmrg 	        pScrn->driverVersion = SAVAGE_VERSION;
961ab47cfaaSmrg	        pScrn->driverName = SAVAGE_DRIVER_NAME;
962ab47cfaaSmrg	        pScrn->name = "SAVAGE";
963ab47cfaaSmrg	        pScrn->Probe = SavageProbe;
964ab47cfaaSmrg	        pScrn->PreInit = SavagePreInit;
965ab47cfaaSmrg	        pScrn->ScreenInit = SavageScreenInit;
966ab47cfaaSmrg	        pScrn->SwitchMode = SavageSwitchMode;
967ab47cfaaSmrg	        pScrn->AdjustFrame = SavageAdjustFrame;
968ab47cfaaSmrg	        pScrn->EnterVT = SavageEnterVT;
969ab47cfaaSmrg	        pScrn->LeaveVT = SavageLeaveVT;
970ab47cfaaSmrg	        pScrn->FreeScreen = NULL;
971ab47cfaaSmrg	        pScrn->ValidMode = SavageValidMode;
972ab47cfaaSmrg	        foundScreen = TRUE;
9738697ee19Smrg
9748697ee19Smrg		if (!SavageGetRec(pScrn))
9758697ee19Smrg		    return FALSE;
9768697ee19Smrg
9778697ee19Smrg		psav = SAVPTR(pScrn);
9788697ee19Smrg
9798697ee19Smrg		psav->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
9808697ee19Smrg		if (pEnt->device->chipset && *pEnt->device->chipset) {
9818697ee19Smrg		    psav->Chipset = xf86StringToToken(SavageChipsets,
9828697ee19Smrg						      pEnt->device->chipset);
9838697ee19Smrg		} else if (pEnt->device->chipID >= 0) {
9848697ee19Smrg		    psav->Chipset = LookupChipID(SavagePciChipsets,
9858697ee19Smrg						 pEnt->device->chipID);
9868697ee19Smrg		} else {
9878697ee19Smrg		    psav->Chipset = LookupChipID(SavagePciChipsets,
9888697ee19Smrg						 psav->PciInfo->chipType);
9898697ee19Smrg		}
990ab47cfaaSmrg	    }
991ab47cfaaSmrg
992ab47cfaaSmrg            pEnt = xf86GetEntityInfo(usedChips[i]);
993ab47cfaaSmrg
994ab47cfaaSmrg            /* MX, IX, SuperSavage cards support Dual-Head, mark the entity as sharable*/
995ab47cfaaSmrg            if(pEnt->chipset == S3_SAVAGE_MX || pEnt->chipset == S3_SUPERSAVAGE)
996ab47cfaaSmrg            {
997ab47cfaaSmrg		DevUnion   *pPriv;
998ab47cfaaSmrg		SavageEntPtr pSavageEnt;
999ab47cfaaSmrg
1000ab47cfaaSmrg		xf86SetEntitySharable(usedChips[i]);
1001ab47cfaaSmrg
1002ab47cfaaSmrg		if (gSavageEntityIndex == -1)
1003ab47cfaaSmrg		    gSavageEntityIndex = xf86AllocateEntityPrivateIndex();
1004ab47cfaaSmrg
1005ab47cfaaSmrg		pPriv = xf86GetEntityPrivate(pEnt->index,
1006ab47cfaaSmrg					     gSavageEntityIndex);
1007ab47cfaaSmrg
1008ab47cfaaSmrg		if (!pPriv->ptr) {
1009ab47cfaaSmrg		    int j;
1010ab47cfaaSmrg		    int instance = xf86GetNumEntityInstances(pEnt->index);
1011ab47cfaaSmrg
1012ab47cfaaSmrg		    for (j = 0; j < instance; j++)
1013ab47cfaaSmrg			xf86SetEntityInstanceForScreen(pScrn, pEnt->index, j);
1014ab47cfaaSmrg
1015ab47cfaaSmrg		    pPriv->ptr = xnfcalloc(sizeof(SavageEntRec), 1);
1016ab47cfaaSmrg		    pSavageEnt = pPriv->ptr;
1017ab47cfaaSmrg		    pSavageEnt->HasSecondary = FALSE;
1018ab47cfaaSmrg		} else {
1019ab47cfaaSmrg		    pSavageEnt = pPriv->ptr;
1020ab47cfaaSmrg		    pSavageEnt->HasSecondary = TRUE;
1021ab47cfaaSmrg		}
1022ab47cfaaSmrg	    }
1023ab47cfaaSmrg	    xfree(pEnt);
1024ab47cfaaSmrg	}
1025ab47cfaaSmrg
1026ab47cfaaSmrg
1027ab47cfaaSmrg    xfree(usedChips);
1028ab47cfaaSmrg    return foundScreen;
1029ab47cfaaSmrg}
1030ab47cfaaSmrg
1031ab47cfaaSmrgstatic int LookupChipID( PciChipsets* pset, int ChipID )
1032ab47cfaaSmrg{
1033ab47cfaaSmrg    /* Is there a function to do this for me? */
1034ab47cfaaSmrg    while( pset->numChipset >= 0 )
1035ab47cfaaSmrg    {
1036ab47cfaaSmrg        if( pset->PCIid == ChipID )
1037ab47cfaaSmrg	    return pset->numChipset;
1038ab47cfaaSmrg	pset++;
1039ab47cfaaSmrg    }
1040ab47cfaaSmrg
1041ab47cfaaSmrg    return -1;
1042ab47cfaaSmrg}
10438697ee19Smrg#endif
1044ab47cfaaSmrg
1045ab47cfaaSmrgstatic void SavageDoDDC(ScrnInfoPtr pScrn)
1046ab47cfaaSmrg{
1047ab47cfaaSmrg    SavagePtr psav= SAVPTR(pScrn);
1048ab47cfaaSmrg    pointer ddc;
1049ab47cfaaSmrg
1050ab47cfaaSmrg    /* Do the DDC dance. */ /* S3/VIA's DDC code */
1051ab47cfaaSmrg    ddc = xf86LoadSubModule(pScrn, "ddc");
1052ab47cfaaSmrg    if (ddc) {
1053ab47cfaaSmrg        xf86LoaderReqSymLists(ddcSymbols, NULL);
1054ab47cfaaSmrg        switch( psav->Chipset ) {
1055ab47cfaaSmrg            case S3_SAVAGE3D:
1056ab47cfaaSmrg            case S3_SAVAGE_MX:
1057ab47cfaaSmrg            case S3_SUPERSAVAGE:
1058ab47cfaaSmrg	    case S3_SAVAGE2000:
1059ab47cfaaSmrg		psav->DDCPort = 0xAA;
1060ab47cfaaSmrg                psav->I2CPort = 0xA0;
1061ab47cfaaSmrg                break;
1062ab47cfaaSmrg
1063ab47cfaaSmrg            case S3_SAVAGE4:
1064ab47cfaaSmrg            case S3_PROSAVAGE:
1065ab47cfaaSmrg            case S3_TWISTER:
1066ab47cfaaSmrg            case S3_PROSAVAGEDDR:
1067ab47cfaaSmrg                psav->DDCPort = 0xB1;
1068ab47cfaaSmrg                psav->I2CPort = 0xA0;
1069ab47cfaaSmrg                break;
1070ab47cfaaSmrg        }
1071ab47cfaaSmrg
1072ab47cfaaSmrg        if (!SavageDDC1(pScrn->scrnIndex)) {
1073ab47cfaaSmrg            /* DDC1 failed,switch to DDC2 */
1074ab47cfaaSmrg            if (xf86LoadSubModule(pScrn, "i2c")) {
1075ab47cfaaSmrg                xf86LoaderReqSymLists(i2cSymbols,NULL);
1076ab47cfaaSmrg                if (SavageI2CInit(pScrn)) {
1077ab47cfaaSmrg                    unsigned char tmp;
10788697ee19Smrg                    xf86MonPtr pMon;
1079ab47cfaaSmrg
1080ab47cfaaSmrg                    InI2CREG(tmp,psav->DDCPort);
1081ab47cfaaSmrg                    OutI2CREG(tmp | 0x13,psav->DDCPort);
10828697ee19Smrg                    pMon = xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,psav->I2C));
10838697ee19Smrg                    if (!psav->IgnoreEDID) xf86SetDDCproperties(pScrn, pMon);
1084ab47cfaaSmrg                    OutI2CREG(tmp,psav->DDCPort);
1085ab47cfaaSmrg                }
1086ab47cfaaSmrg            }
1087ab47cfaaSmrg        }
1088ab47cfaaSmrg    }
1089ab47cfaaSmrg}
1090ab47cfaaSmrg
1091ab47cfaaSmrg/* Copied from ddc/Property.c via nv */
1092ab47cfaaSmrgstatic DisplayModePtr
1093ab47cfaaSmrgSavageModesAdd(DisplayModePtr Modes, DisplayModePtr Additions)
1094ab47cfaaSmrg{
1095ab47cfaaSmrg    if (!Modes) {
1096ab47cfaaSmrg        if (Additions)
1097ab47cfaaSmrg            return Additions;
1098ab47cfaaSmrg        else
1099ab47cfaaSmrg            return NULL;
1100ab47cfaaSmrg    }
1101ab47cfaaSmrg
1102ab47cfaaSmrg    if (Additions) {
1103ab47cfaaSmrg        DisplayModePtr Mode = Modes;
1104ab47cfaaSmrg
1105ab47cfaaSmrg        while (Mode->next)
1106ab47cfaaSmrg            Mode = Mode->next;
1107ab47cfaaSmrg
1108ab47cfaaSmrg        Mode->next = Additions;
1109ab47cfaaSmrg        Additions->prev = Mode;
1110ab47cfaaSmrg    }
1111ab47cfaaSmrg
1112ab47cfaaSmrg    return Modes;
1113ab47cfaaSmrg}
1114ab47cfaaSmrg
1115ab47cfaaSmrg/* borrowed from nv */
1116ab47cfaaSmrgstatic void
1117ab47cfaaSmrgSavageAddPanelMode(ScrnInfoPtr pScrn)
1118ab47cfaaSmrg{
1119ab47cfaaSmrg    SavagePtr psav= SAVPTR(pScrn);
1120ab47cfaaSmrg    DisplayModePtr  Mode  = NULL;
1121ab47cfaaSmrg
1122ab47cfaaSmrg    Mode = xf86CVTMode(psav->PanelX, psav->PanelY, 60.00, TRUE, FALSE);
1123ab47cfaaSmrg    Mode->type = M_T_DRIVER | M_T_PREFERRED;
1124ab47cfaaSmrg    pScrn->monitor->Modes = SavageModesAdd(pScrn->monitor->Modes, Mode);
1125ab47cfaaSmrg
1126ab47cfaaSmrg    if ((pScrn->monitor->nHsync == 0) &&
1127ab47cfaaSmrg        (pScrn->monitor->nVrefresh == 0)) {
1128ab47cfaaSmrg	if (!Mode->HSync)
1129ab47cfaaSmrg	    Mode->HSync = ((float) Mode->Clock ) / ((float) Mode->HTotal);
1130ab47cfaaSmrg	if (!Mode->VRefresh)
1131ab47cfaaSmrg	    Mode->VRefresh = (1000.0 * ((float) Mode->Clock)) /
1132ab47cfaaSmrg		((float) (Mode->HTotal * Mode->VTotal));
1133ab47cfaaSmrg
1134ab47cfaaSmrg	if (Mode->HSync < pScrn->monitor->hsync[0].lo)
1135ab47cfaaSmrg	    pScrn->monitor->hsync[0].lo = Mode->HSync;
1136ab47cfaaSmrg	if (Mode->HSync > pScrn->monitor->hsync[0].hi)
1137ab47cfaaSmrg	    pScrn->monitor->hsync[0].hi = Mode->HSync;
1138ab47cfaaSmrg	if (Mode->VRefresh < pScrn->monitor->vrefresh[0].lo)
1139ab47cfaaSmrg	    pScrn->monitor->vrefresh[0].lo = Mode->VRefresh;
1140ab47cfaaSmrg	if (Mode->VRefresh > pScrn->monitor->vrefresh[0].hi)
1141ab47cfaaSmrg	    pScrn->monitor->vrefresh[0].hi = Mode->VRefresh;
1142ab47cfaaSmrg
1143ab47cfaaSmrg	pScrn->monitor->nHsync = 1;
1144ab47cfaaSmrg	pScrn->monitor->nVrefresh = 1;
1145ab47cfaaSmrg    }
1146ab47cfaaSmrg}
1147ab47cfaaSmrg
1148ab47cfaaSmrgstatic void SavageGetPanelInfo(ScrnInfoPtr pScrn)
1149ab47cfaaSmrg{
1150ab47cfaaSmrg    SavagePtr psav= SAVPTR(pScrn);
1151ab47cfaaSmrg    vgaHWPtr hwp;
1152ab47cfaaSmrg    unsigned char cr6b;
1153ab47cfaaSmrg    int panelX, panelY;
1154ab47cfaaSmrg    char * sTechnology = "Unknown";
1155ab47cfaaSmrg    enum ACTIVE_DISPLAYS { /* These are the bits in CR6B */
1156ab47cfaaSmrg	ActiveCRT = 0x01,
1157ab47cfaaSmrg	ActiveLCD = 0x02,
1158ab47cfaaSmrg	ActiveTV = 0x04,
1159ab47cfaaSmrg	ActiveCRT2 = 0x20,
1160ab47cfaaSmrg	ActiveDUO = 0x80
1161ab47cfaaSmrg    };
1162ab47cfaaSmrg
1163ab47cfaaSmrg    hwp = VGAHWPTR(pScrn);
1164ab47cfaaSmrg
1165ab47cfaaSmrg    /* Check LCD panel information */
1166ab47cfaaSmrg
1167ab47cfaaSmrg    cr6b = hwp->readCrtc( hwp, 0x6b );
1168ab47cfaaSmrg
1169ab47cfaaSmrg    panelX = (hwp->readSeq(hwp, 0x61) +
1170ab47cfaaSmrg	    ((hwp->readSeq(hwp, 0x66) & 0x02) << 7) + 1) * 8;
1171ab47cfaaSmrg    panelY = hwp->readSeq(hwp, 0x69) +
1172ab47cfaaSmrg	    ((hwp->readSeq(hwp, 0x6e) & 0x70) << 4) + 1;
1173ab47cfaaSmrg
1174ab47cfaaSmrg
1175ab47cfaaSmrg	/* OK, I admit it.  I don't know how to limit the max dot clock
1176ab47cfaaSmrg	 * for LCD panels of various sizes.  I thought I copied the formula
1177ab47cfaaSmrg	 * from the BIOS, but many users have informed me of my folly.
1178ab47cfaaSmrg	 *
1179ab47cfaaSmrg	 * Instead, I'll abandon any attempt to automatically limit the
1180ab47cfaaSmrg	 * clock, and add an LCDClock option to XF86Config.  Some day,
1181ab47cfaaSmrg	 * I should come back to this.
1182ab47cfaaSmrg	 */
1183ab47cfaaSmrg
1184ab47cfaaSmrg
1185ab47cfaaSmrg    if( (hwp->readSeq( hwp, 0x39 ) & 0x03) == 0 )
1186ab47cfaaSmrg    {
1187ab47cfaaSmrg	sTechnology = "TFT";
1188ab47cfaaSmrg    }
1189ab47cfaaSmrg    else if( (hwp->readSeq( hwp, 0x30 ) & 0x01) == 0 )
1190ab47cfaaSmrg    {
1191ab47cfaaSmrg	sTechnology = "DSTN";
1192ab47cfaaSmrg    }
1193ab47cfaaSmrg    else
1194ab47cfaaSmrg    {
1195ab47cfaaSmrg	sTechnology = "STN";
1196ab47cfaaSmrg    }
1197ab47cfaaSmrg
1198ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1199ab47cfaaSmrg		   "%dx%d %s LCD panel detected %s\n",
1200ab47cfaaSmrg		   panelX, panelY, sTechnology,
1201ab47cfaaSmrg		   cr6b & ActiveLCD ? "and active" : "but not active");
1202ab47cfaaSmrg
1203ab47cfaaSmrg    if( cr6b & ActiveLCD ) {
1204ab47cfaaSmrg	    /* If the LCD is active and panel expansion is enabled, */
1205ab47cfaaSmrg	    /* we probably want to kill the HW cursor. */
1206ab47cfaaSmrg
1207ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
1208ab47cfaaSmrg		       "- Limiting video mode to %dx%d\n",
1209ab47cfaaSmrg		       panelX, panelY );
1210ab47cfaaSmrg
1211ab47cfaaSmrg	psav->PanelX = panelX;
1212ab47cfaaSmrg	psav->PanelY = panelY;
1213ab47cfaaSmrg
12148697ee19Smrg	do {
12158697ee19Smrg	    DisplayModePtr native = xf86CVTMode(panelX, panelY, 60.0, 0, 0);
12168697ee19Smrg	    if (!native)
12178697ee19Smrg		break;
12188697ee19Smrg
12198697ee19Smrg	    if (!pScrn->monitor->nHsync) {
12208697ee19Smrg		pScrn->monitor->nHsync = 1;
12218697ee19Smrg		pScrn->monitor->hsync[0].lo = 31.5;
12228697ee19Smrg		pScrn->monitor->hsync[0].hi = (float)native->Clock /
12238697ee19Smrg					      (float)native->HTotal;
12248697ee19Smrg	    }
12258697ee19Smrg	    if (!pScrn->monitor->nVrefresh) {
12268697ee19Smrg		pScrn->monitor->nVrefresh = 1;
12278697ee19Smrg		pScrn->monitor->vrefresh[0].lo = 56.0;
12288697ee19Smrg		pScrn->monitor->vrefresh[0].hi = (float)native->Clock * 1000.0 /
12298697ee19Smrg						 (float)native->HTotal /
12308697ee19Smrg						 (float)native->VTotal;
12318697ee19Smrg	    }
12328697ee19Smrg	    if (!pScrn->monitor->maxPixClock)
12338697ee19Smrg		pScrn->monitor->maxPixClock = native->Clock;
12348697ee19Smrg
12358697ee19Smrg	    xfree(native);
12368697ee19Smrg	} while (0);
12378697ee19Smrg
1238ab47cfaaSmrg	if( psav->LCDClock > 0.0 )
1239ab47cfaaSmrg	{
1240ab47cfaaSmrg	    psav->maxClock = psav->LCDClock * 1000.0;
1241ab47cfaaSmrg	    xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1242ab47cfaaSmrg			    "- Limiting dot clock to %1.2f MHz\n",
1243ab47cfaaSmrg			    psav->LCDClock );
1244ab47cfaaSmrg	}
1245ab47cfaaSmrg    } else {
1246ab47cfaaSmrg        psav->DisplayType = MT_CRT;
1247ab47cfaaSmrg    }
1248ab47cfaaSmrg}
1249ab47cfaaSmrg
1250ab47cfaaSmrg
1251ab47cfaaSmrgstatic Bool SavagePreInit(ScrnInfoPtr pScrn, int flags)
1252ab47cfaaSmrg{
1253ab47cfaaSmrg    EntityInfoPtr pEnt;
1254ab47cfaaSmrg    SavagePtr psav;
1255ab47cfaaSmrg    MessageType from = X_DEFAULT;
1256ab47cfaaSmrg    int i;
1257ab47cfaaSmrg    ClockRangePtr clockRanges;
1258ab47cfaaSmrg    char *s = NULL;
1259ab47cfaaSmrg    unsigned char config1, m, n, n1, n2, sr8, cr66 = 0, tmp;
1260ab47cfaaSmrg    int mclk;
1261ab47cfaaSmrg    vgaHWPtr hwp;
1262ab47cfaaSmrg    int vgaCRIndex, vgaCRReg;
1263ab47cfaaSmrg    Bool dvi;
1264ab47cfaaSmrg
1265ab47cfaaSmrg    TRACE(("SavagePreInit(%d)\n", flags));
1266ab47cfaaSmrg
1267ab47cfaaSmrg    gpScrn = pScrn;
1268ab47cfaaSmrg
1269ab47cfaaSmrg    if (flags & PROBE_DETECT) {
1270ab47cfaaSmrg	SavageProbeDDC( pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index );
1271ab47cfaaSmrg	return TRUE;
1272ab47cfaaSmrg    }
1273ab47cfaaSmrg
1274ab47cfaaSmrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
1275ab47cfaaSmrg	return FALSE;
1276ab47cfaaSmrg
1277ab47cfaaSmrg    xf86LoaderReqSymLists(vgaHWSymbols, NULL);
1278ab47cfaaSmrg    if (!vgaHWGetHWRec(pScrn))
1279ab47cfaaSmrg	return FALSE;
1280ab47cfaaSmrg
1281ab47cfaaSmrg#if 0
1282ab47cfaaSmrg    /* Here we can alter the number of registers saved and restored by the
1283ab47cfaaSmrg     * standard vgaHWSave and Restore routines.
1284ab47cfaaSmrg     */
1285ab47cfaaSmrg    vgaHWSetRegCounts( pScrn, VGA_NUM_CRTC, VGA_NUM_SEQ, VGA_NUM_GFX, VGA_NUM_ATTR );
1286ab47cfaaSmrg#endif
1287ab47cfaaSmrg
1288ab47cfaaSmrg    pScrn->monitor = pScrn->confScreen->monitor;
1289ab47cfaaSmrg
1290ab47cfaaSmrg    /*
1291ab47cfaaSmrg     * We support depths of 8, 15, 16 and 24.
1292ab47cfaaSmrg     * We support bpp of 8, 16, and 32.
1293ab47cfaaSmrg     */
1294ab47cfaaSmrg
1295ab47cfaaSmrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
1296ab47cfaaSmrg	return FALSE;
1297ab47cfaaSmrg    else {
1298ab47cfaaSmrg        int requiredBpp;
1299ab47cfaaSmrg	int altBpp = 0;
1300ab47cfaaSmrg
1301ab47cfaaSmrg	switch (pScrn->depth) {
1302ab47cfaaSmrg	case 8:
1303ab47cfaaSmrg	case 16:
1304ab47cfaaSmrg	    requiredBpp = pScrn->depth;
1305ab47cfaaSmrg	    break;
1306ab47cfaaSmrg	case 15:
1307ab47cfaaSmrg	    requiredBpp = 16;
1308ab47cfaaSmrg	    break;
1309ab47cfaaSmrg	case 24:
1310ab47cfaaSmrg	    requiredBpp = 32;
1311ab47cfaaSmrg	    altBpp = 24;
1312ab47cfaaSmrg	    break;
1313ab47cfaaSmrg
1314ab47cfaaSmrg	default:
1315ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1316ab47cfaaSmrg		       "Given depth (%d) is not supported by this driver\n",
1317ab47cfaaSmrg			pScrn->depth);
1318ab47cfaaSmrg	    return FALSE;
1319ab47cfaaSmrg	}
1320ab47cfaaSmrg
1321ab47cfaaSmrg	if(
1322ab47cfaaSmrg	    (pScrn->bitsPerPixel != requiredBpp) &&
1323ab47cfaaSmrg	    (pScrn->bitsPerPixel != altBpp)
1324ab47cfaaSmrg	) {
1325ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1326ab47cfaaSmrg		       "Depth %d must specify %d bpp; %d was given\n",
1327ab47cfaaSmrg		       pScrn->depth, requiredBpp, pScrn->bitsPerPixel );
1328ab47cfaaSmrg	    return FALSE;
1329ab47cfaaSmrg	}
1330ab47cfaaSmrg    }
1331ab47cfaaSmrg
1332ab47cfaaSmrg    xf86PrintDepthBpp(pScrn);
1333ab47cfaaSmrg
1334ab47cfaaSmrg    if (pScrn->depth > 8) {
1335ab47cfaaSmrg	rgb zeros = {0, 0, 0};
1336ab47cfaaSmrg
1337ab47cfaaSmrg	if (!xf86SetWeight(pScrn, zeros, zeros))
1338ab47cfaaSmrg	    return FALSE;
1339ab47cfaaSmrg	else {
1340ab47cfaaSmrg	    /* TODO check weight returned is supported */
1341ab47cfaaSmrg	    ;
1342ab47cfaaSmrg	}
1343ab47cfaaSmrg    }
1344ab47cfaaSmrg
1345ab47cfaaSmrg    if (!xf86SetDefaultVisual(pScrn, -1)) {
1346ab47cfaaSmrg	return FALSE;
1347ab47cfaaSmrg    } else {
1348ab47cfaaSmrg	/* We don't currently support DirectColor at 16bpp */
1349ab47cfaaSmrg	if (pScrn->bitsPerPixel == 16 && pScrn->defaultVisual != TrueColor) {
1350ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
1351ab47cfaaSmrg		       " (%s) is not supported at depth %d\n",
1352ab47cfaaSmrg		       xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
1353ab47cfaaSmrg	    return FALSE;
1354ab47cfaaSmrg	}
1355ab47cfaaSmrg    }
1356ab47cfaaSmrg
1357ab47cfaaSmrg    pScrn->progClock = TRUE;
1358ab47cfaaSmrg
1359ab47cfaaSmrg    if (!SavageGetRec(pScrn))
1360ab47cfaaSmrg	return FALSE;
1361ab47cfaaSmrg    psav = SAVPTR(pScrn);
1362ab47cfaaSmrg
1363ab47cfaaSmrg    hwp = VGAHWPTR(pScrn);
1364ab47cfaaSmrg    vgaHWGetIOBase(hwp);
1365ab47cfaaSmrg    psav->vgaIOBase = hwp->IOBase;
1366ab47cfaaSmrg
1367ab47cfaaSmrg    xf86CollectOptions(pScrn, NULL);
1368ab47cfaaSmrg
1369ab47cfaaSmrg    if (pScrn->depth == 8)
1370ab47cfaaSmrg	pScrn->rgbBits = 8;
1371ab47cfaaSmrg
1372ab47cfaaSmrg    if (!(psav->Options = xalloc(sizeof(SavageOptions))))
1373ab47cfaaSmrg	return FALSE;
1374ab47cfaaSmrg    memcpy(psav->Options, SavageOptions, sizeof(SavageOptions));
1375ab47cfaaSmrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, psav->Options);
1376ab47cfaaSmrg
13778697ee19Smrg    xf86GetOptValBool(psav->Options, OPTION_IGNORE_EDID, &psav->IgnoreEDID);
1378ab47cfaaSmrg    xf86GetOptValBool(psav->Options, OPTION_PCI_BURST, &psav->pci_burst);
1379ab47cfaaSmrg
1380ab47cfaaSmrg    if (psav->pci_burst) {
1381ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1382ab47cfaaSmrg		   "Option: pci_burst - PCI burst read enabled\n");
1383ab47cfaaSmrg    }
1384ab47cfaaSmrg
1385ab47cfaaSmrg    psav->NoPCIRetry = 1;		/* default */
1386ab47cfaaSmrg    if (xf86ReturnOptValBool(psav->Options, OPTION_PCI_RETRY, FALSE)) {
1387ab47cfaaSmrg	if (xf86ReturnOptValBool(psav->Options, OPTION_PCI_BURST, FALSE)) {
1388ab47cfaaSmrg	    psav->NoPCIRetry = 0;
1389ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: pci_retry\n");
1390ab47cfaaSmrg	} else
1391ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"pci_retry\" option requires \"pci_burst\"\n");
1392ab47cfaaSmrg    }
1393ab47cfaaSmrg
1394ab47cfaaSmrg    xf86GetOptValBool( psav->Options, OPTION_SHADOW_FB, &psav->shadowFB );
1395ab47cfaaSmrg    if (psav->shadowFB) {
1396ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: shadow FB enabled\n");
1397ab47cfaaSmrg    }
1398ab47cfaaSmrg
1399ab47cfaaSmrg    psav->primStreamBpp = pScrn->bitsPerPixel;
1400ab47cfaaSmrg
1401ab47cfaaSmrg    if ((s = xf86GetOptValString(psav->Options, OPTION_ROTATE))) {
1402ab47cfaaSmrg	if(!xf86NameCmp(s, "CW")) {
1403ab47cfaaSmrg	    /* accel is disabled below for shadowFB */
1404ab47cfaaSmrg             /* RandR is disabled when the Rotate option is used (does
1405ab47cfaaSmrg              * not work well together and scrambles the screen) */
1406ab47cfaaSmrg
1407ab47cfaaSmrg	    psav->shadowFB = TRUE;
1408ab47cfaaSmrg	    psav->rotate = 1;
1409ab47cfaaSmrg            xf86DisableRandR();
1410ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1411ab47cfaaSmrg		       "Rotating screen clockwise"
1412ab47cfaaSmrg                       "- acceleration and RandR disabled\n");
1413ab47cfaaSmrg	} else if(!xf86NameCmp(s, "CCW")) {
1414ab47cfaaSmrg	    psav->shadowFB = TRUE;
1415ab47cfaaSmrg	    psav->rotate = -1;
1416ab47cfaaSmrg            xf86DisableRandR();
1417ab47cfaaSmrg            xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1418ab47cfaaSmrg                   "Rotating screen counter clockwise"
1419ab47cfaaSmrg                   " - acceleration and RandR disabled\n");
1420ab47cfaaSmrg
1421ab47cfaaSmrg	} else {
1422ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
1423ab47cfaaSmrg		       "value for Option \"Rotate\"\n", s);
1424ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1425ab47cfaaSmrg		       "Valid options are \"CW\" or \"CCW\"\n");
1426ab47cfaaSmrg	}
1427ab47cfaaSmrg    }
1428ab47cfaaSmrg
1429ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_NOACCEL, &psav->NoAccel))
1430ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1431ab47cfaaSmrg		    "Option: NoAccel - Acceleration Disabled\n");
1432ab47cfaaSmrg
1433ab47cfaaSmrg    if (psav->shadowFB && !psav->NoAccel) {
1434ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1435ab47cfaaSmrg		   "HW acceleration not supported with \"shadowFB\".\n");
1436ab47cfaaSmrg	psav->NoAccel = TRUE;
1437ab47cfaaSmrg    }
1438ab47cfaaSmrg
1439ab47cfaaSmrg    if(!psav->NoAccel) {
1440ab47cfaaSmrg        from = X_DEFAULT;
1441ab47cfaaSmrg	char *strptr;
1442ab47cfaaSmrg        if((strptr = (char *)xf86GetOptValString(psav->Options, OPTION_ACCELMETHOD))) {
1443ab47cfaaSmrg	    if(!xf86NameCmp(strptr,"XAA")) {
1444ab47cfaaSmrg	        from = X_CONFIG;
1445ab47cfaaSmrg	        psav->useEXA = FALSE;
1446ab47cfaaSmrg	    } else if(!xf86NameCmp(strptr,"EXA")) {
1447ab47cfaaSmrg	       from = X_CONFIG;
1448ab47cfaaSmrg	       psav->useEXA = TRUE;
1449ab47cfaaSmrg	    }
1450ab47cfaaSmrg       }
1451ab47cfaaSmrg       xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
1452ab47cfaaSmrg		psav->useEXA ? "EXA" : "XAA");
1453ab47cfaaSmrg    }
1454ab47cfaaSmrg
1455ab47cfaaSmrg    if ((s = xf86GetOptValString(psav->Options, OPTION_OVERLAY))) {
1456ab47cfaaSmrg
1457ab47cfaaSmrg	if (psav->shadowFB) {
1458ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex,X_INFO,
1459ab47cfaaSmrg		       "Option \"Overlay\" not supported with shadowFB\n");
1460ab47cfaaSmrg	} else {
1461ab47cfaaSmrg	    if (pScrn->depth == 8) {
1462ab47cfaaSmrg		if (!*s || !xf86NameCmp(s, "24")) {
1463ab47cfaaSmrg		    psav->overlayDepth = 24;
1464ab47cfaaSmrg		    psav->NoAccel = TRUE; /* Preliminary */
1465ab47cfaaSmrg		    pScrn->colorKey = TRANSPARENCY_KEY;
1466ab47cfaaSmrg		    pScrn->overlayFlags = OVERLAY_8_32_DUALFB;
1467ab47cfaaSmrg		} else if (!xf86NameCmp(s, "16")) {
1468ab47cfaaSmrg		    psav->overlayDepth = 16;
1469ab47cfaaSmrg		    psav->NoAccel = TRUE; /* Preliminary */
1470ab47cfaaSmrg		    pScrn->colorKey = TRANSPARENCY_KEY;
1471ab47cfaaSmrg		    pScrn->overlayFlags = OVERLAY_8_32_DUALFB;
1472ab47cfaaSmrg		} else {
1473ab47cfaaSmrg		    xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: "
1474ab47cfaaSmrg			       "\"%s\" Ingnoring\n",s);
1475ab47cfaaSmrg		}
1476ab47cfaaSmrg	    } else if (pScrn->depth != 15) {
1477ab47cfaaSmrg		psav->overlayDepth = 8;
1478ab47cfaaSmrg		psav->NoAccel = TRUE; /* Preliminary */
1479ab47cfaaSmrg		pScrn->colorKey = TRANSPARENCY_KEY;
1480ab47cfaaSmrg		pScrn->overlayFlags = OVERLAY_8_32_DUALFB;
1481ab47cfaaSmrg		if (*s && (xf86NameCmp(s, "8")))
1482ab47cfaaSmrg		    xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Wrong argument: "
1483ab47cfaaSmrg			       "\"%s\" for depth %i overlay depth must be 8\n",
1484ab47cfaaSmrg			       s,pScrn->depth);
1485ab47cfaaSmrg	    } else {
1486ab47cfaaSmrg		 xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"Overlay not "
1487ab47cfaaSmrg			       "supported for depth 15\n");
1488ab47cfaaSmrg	    }
1489ab47cfaaSmrg	    if (psav->overlayDepth) {
1490ab47cfaaSmrg		xf86DrvMsg(pScrn->scrnIndex,X_INFO,"%i/%i Overlay enabled\n",
1491ab47cfaaSmrg			   pScrn->depth,psav->overlayDepth);
1492ab47cfaaSmrg		psav->primStreamBpp = 8;
1493ab47cfaaSmrg	    }
1494ab47cfaaSmrg	}
1495ab47cfaaSmrg    }
1496ab47cfaaSmrg
1497ab47cfaaSmrg    if (pScrn->bitsPerPixel == 24 && !psav->NoAccel) {
1498ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1499ab47cfaaSmrg		   "HW acceleration not possible with depth 32 and bpp 24.\n");
1500ab47cfaaSmrg	psav->NoAccel = TRUE;
1501ab47cfaaSmrg    }
1502ab47cfaaSmrg
1503ab47cfaaSmrg    /*
1504ab47cfaaSmrg     * The SWCursor setting takes priority over HWCursor.  The default
1505ab47cfaaSmrg     * if neither is specified is HW, unless ShadowFB is specified,
1506ab47cfaaSmrg     * then SW.
1507ab47cfaaSmrg     */
1508ab47cfaaSmrg
1509ab47cfaaSmrg    from = X_DEFAULT;
1510ab47cfaaSmrg    psav->hwcursor = psav->shadowFB ? FALSE : TRUE;
1511ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_HWCURSOR, &psav->hwcursor))
1512ab47cfaaSmrg	from = X_CONFIG;
1513ab47cfaaSmrg    if (xf86ReturnOptValBool(psav->Options, OPTION_SWCURSOR, FALSE)) {
1514ab47cfaaSmrg	psav->hwcursor = FALSE;
1515ab47cfaaSmrg	from = X_CONFIG;
1516ab47cfaaSmrg    }
1517ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
1518ab47cfaaSmrg        psav->hwcursor ? "HW" : "SW");
1519ab47cfaaSmrg
1520ab47cfaaSmrg    from = X_DEFAULT;
1521ab47cfaaSmrg    psav->UseBIOS = TRUE;
1522ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_USEBIOS, &psav->UseBIOS) )
1523ab47cfaaSmrg	from = X_CONFIG;
1524ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "%ssing video BIOS to set modes\n",
1525ab47cfaaSmrg        psav->UseBIOS ? "U" : "Not u" );
1526ab47cfaaSmrg
1527ab47cfaaSmrg    psav->LCDClock = 0.0;
1528ab47cfaaSmrg    if( xf86GetOptValFreq( psav->Options, OPTION_LCDCLOCK, OPTUNITS_MHZ, &psav->LCDClock ) )
1529ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1530ab47cfaaSmrg		    "Option: LCDClock %1.2f MHz\n", psav->LCDClock );
1531ab47cfaaSmrg
1532ab47cfaaSmrg    if( xf86GetOptValBool( psav->Options, OPTION_SHADOW_STATUS, &psav->ShadowStatus)) {
1533ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1534ab47cfaaSmrg		    "Option: ShadowStatus %sabled\n", psav->ShadowStatus ? "en" : "dis" );
1535ab47cfaaSmrg	psav->ForceShadowStatus = TRUE;
1536ab47cfaaSmrg    } else
1537ab47cfaaSmrg	psav->ForceShadowStatus = FALSE;
1538ab47cfaaSmrg    /* If ShadowStatus is off it will be automatically enabled for DRI.
1539ab47cfaaSmrg     * If DRI initialization fails fall back to ConfigShadowStatus. */
1540ab47cfaaSmrg    psav->ConfigShadowStatus = psav->ShadowStatus;
1541ab47cfaaSmrg
1542ab47cfaaSmrg    if( xf86GetOptValBool( psav->Options, OPTION_CRT_ONLY, &psav->CrtOnly))
1543ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1544ab47cfaaSmrg		    "Option: CrtOnly enabled\n" );
1545ab47cfaaSmrg
1546ab47cfaaSmrg    if( xf86GetOptValBool( psav->Options, OPTION_TV_ON, &psav->TvOn)) {
1547ab47cfaaSmrg        psav->PAL = FALSE;
1548ab47cfaaSmrg        SavageGetTvMaxSize(psav);
1549ab47cfaaSmrg    }
1550ab47cfaaSmrg
1551ab47cfaaSmrg    if( xf86GetOptValBool( psav->Options, OPTION_TV_PAL, &psav->PAL)) {
1552ab47cfaaSmrg        SavageGetTvMaxSize(psav);
1553ab47cfaaSmrg	psav->TvOn = TRUE;
1554ab47cfaaSmrg    }
1555ab47cfaaSmrg
1556ab47cfaaSmrg    if( psav->TvOn )
1557ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1558ab47cfaaSmrg		    "TV enabled in %s format\n",
1559ab47cfaaSmrg		    psav->PAL ? "PAL" : "NTSC" );
1560ab47cfaaSmrg
1561ab47cfaaSmrg    psav->ForceInit = 0;
1562ab47cfaaSmrg    if( xf86GetOptValBool( psav->Options, OPTION_FORCE_INIT, &psav->ForceInit))
1563ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_CONFIG,
1564ab47cfaaSmrg		    "Option: ForceInit enabled\n" );
1565ab47cfaaSmrg
1566ab47cfaaSmrg    if (pScrn->numEntities > 1) {
1567ab47cfaaSmrg	SavageFreeRec(pScrn);
1568ab47cfaaSmrg	return FALSE;
1569ab47cfaaSmrg    }
1570ab47cfaaSmrg
1571ab47cfaaSmrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1572ab47cfaaSmrg    if (pEnt->resources) {
1573ab47cfaaSmrg	xfree(pEnt);
1574ab47cfaaSmrg	SavageFreeRec(pScrn);
1575ab47cfaaSmrg	return FALSE;
1576ab47cfaaSmrg    }
1577ab47cfaaSmrg    psav->EntityIndex = pEnt->index;
1578ab47cfaaSmrg
1579ab47cfaaSmrg    if (xf86LoadSubModule(pScrn, "vbe")) {
1580ab47cfaaSmrg	xf86LoaderReqSymLists(vbeSymbols, NULL);
1581ab47cfaaSmrg	psav->pVbe = VBEInit(NULL, pEnt->index);
1582ab47cfaaSmrg    }
1583ab47cfaaSmrg
1584ab47cfaaSmrg    xf86RegisterResources(pEnt->index, NULL, ResNone);
1585ab47cfaaSmrg    xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr);
1586ab47cfaaSmrg    xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr);
1587ab47cfaaSmrg
1588ab47cfaaSmrg    from = X_DEFAULT;
1589ab47cfaaSmrg    if (pEnt->device->chipset && *pEnt->device->chipset) {
1590ab47cfaaSmrg	pScrn->chipset = pEnt->device->chipset;
1591ab47cfaaSmrg	psav->ChipId = pEnt->device->chipID;
1592ab47cfaaSmrg	from = X_CONFIG;
1593ab47cfaaSmrg    } else if (pEnt->device->chipID >= 0) {
1594ab47cfaaSmrg	psav->ChipId = pEnt->device->chipID;
1595ab47cfaaSmrg	pScrn->chipset = (char *)xf86TokenToString(SavageChipsets,
1596ab47cfaaSmrg						   psav->Chipset);
1597ab47cfaaSmrg	from = X_CONFIG;
1598ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
1599ab47cfaaSmrg		   pEnt->device->chipID);
1600ab47cfaaSmrg    } else {
1601ab47cfaaSmrg	from = X_PROBED;
16028697ee19Smrg	psav->ChipId = DEVICE_ID(psav->PciInfo);
1603ab47cfaaSmrg	pScrn->chipset = (char *)xf86TokenToString(SavageChipsets,
1604ab47cfaaSmrg						   psav->Chipset);
1605ab47cfaaSmrg    }
1606ab47cfaaSmrg
1607ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Chip: id %04x, \"%s\"\n",
1608ab47cfaaSmrg	       psav->ChipId, xf86TokenToString( SavageChips, psav->ChipId ) );
1609ab47cfaaSmrg
1610ab47cfaaSmrg    if (pEnt->device->chipRev >= 0) {
1611ab47cfaaSmrg	psav->ChipRev = pEnt->device->chipRev;
1612ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
1613ab47cfaaSmrg		   psav->ChipRev);
1614ab47cfaaSmrg    } else
16158697ee19Smrg	psav->ChipRev = CHIP_REVISION(psav->PciInfo);
1616ab47cfaaSmrg
1617ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, from, "Engine: \"%s\"\n", pScrn->chipset);
1618ab47cfaaSmrg
1619ab47cfaaSmrg    if (pEnt->device->videoRam != 0)
1620ab47cfaaSmrg    	pScrn->videoRam = pEnt->device->videoRam;
1621ab47cfaaSmrg
1622ab47cfaaSmrg    xfree(pEnt);
1623ab47cfaaSmrg
16248697ee19Smrg#ifndef XSERVER_LIBPCIACCESS
1625ab47cfaaSmrg    psav->PciTag = pciTag(psav->PciInfo->bus, psav->PciInfo->device,
1626ab47cfaaSmrg			  psav->PciInfo->func);
16278697ee19Smrg#endif
1628ab47cfaaSmrg
1629ab47cfaaSmrg
1630ab47cfaaSmrg    /* Set AGP Mode from config */
1631ab47cfaaSmrg    /* We support 1X 2X and 4X  */
1632ab47cfaaSmrg#ifdef XF86DRI
16338697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
16348697ee19Smrg    /* Try to read the AGP capabilty block from the device.  If there is
16358697ee19Smrg     * no AGP info, the device is PCI.
16368697ee19Smrg     */
16378697ee19Smrg
16388697ee19Smrg    psav->IsPCI = (pci_device_get_agp_info(psav->PciInfo) == NULL);
16398697ee19Smrg#else
1640ab47cfaaSmrg				/* AGP/PCI (FK: copied from radeon_driver.c) */
1641ab47cfaaSmrg    /* Proper autodetection of an AGP capable device requires examining
1642ab47cfaaSmrg     * PCI config registers to determine if the device implements extended
1643ab47cfaaSmrg     * PCI capabilities, and then walking the capability list as indicated
1644ab47cfaaSmrg     * in the PCI 2.2 and AGP 2.0 specifications, to determine if AGP
1645ab47cfaaSmrg     * capability is present.  The procedure is outlined as follows:
1646ab47cfaaSmrg     *
1647ab47cfaaSmrg     * 1) Test bit 4 (CAP_LIST) of the PCI status register of the device
1648ab47cfaaSmrg     *    to determine wether or not this device implements any extended
1649ab47cfaaSmrg     *    capabilities.  If this bit is zero, then the device is a PCI 2.1
1650ab47cfaaSmrg     *    or earlier device and is not AGP capable, and we can conclude it
1651ab47cfaaSmrg     *    to be a PCI device.
1652ab47cfaaSmrg     *
1653ab47cfaaSmrg     * 2) If bit 4 of the status register is set, then the device implements
1654ab47cfaaSmrg     *    extended capabilities.  There is an 8 bit wide capabilities pointer
1655ab47cfaaSmrg     *    register located at offset 0x34 in PCI config space which points to
1656ab47cfaaSmrg     *    the first capability in a linked list of extended capabilities that
1657ab47cfaaSmrg     *    this device implements.  The lower two bits of this register are
1658ab47cfaaSmrg     *    reserved and MBZ so must be masked out.
1659ab47cfaaSmrg     *
1660ab47cfaaSmrg     * 3) The extended capabilities list is formed by one or more extended
1661ab47cfaaSmrg     *    capabilities structures which are aligned on DWORD boundaries.
1662ab47cfaaSmrg     *    The first byte of the structure is the capability ID (CAP_ID)
1663ab47cfaaSmrg     *    indicating what extended capability this structure refers to.  The
1664ab47cfaaSmrg     *    second byte of the structure is an offset from the beginning of
1665ab47cfaaSmrg     *    PCI config space pointing to the next capability in the linked
1666ab47cfaaSmrg     *    list (NEXT_PTR) or NULL (0x00) at the end of the list.  The lower
1667ab47cfaaSmrg     *    two bits of this pointer are reserved and MBZ.  By examining the
1668ab47cfaaSmrg     *    CAP_ID of each capability and walking through the list, we will
1669ab47cfaaSmrg     *    either find the AGP_CAP_ID (0x02) indicating this device is an
1670ab47cfaaSmrg     *    AGP device, or we'll reach the end of the list, indicating it is
1671ab47cfaaSmrg     *    a PCI device.
1672ab47cfaaSmrg     *
1673ab47cfaaSmrg     * Mike A. Harris <mharris@redhat.com>
1674ab47cfaaSmrg     *
1675ab47cfaaSmrg     * References:
1676ab47cfaaSmrg     *	- PCI Local Bus Specification Revision 2.2, Chapter 6
1677ab47cfaaSmrg     *	- AGP Interface Specification Revision 2.0, Section 6.1.5
1678ab47cfaaSmrg     */
1679ab47cfaaSmrg
1680ab47cfaaSmrg    psav->IsPCI = TRUE;
1681ab47cfaaSmrg
1682ab47cfaaSmrg    if (pciReadLong(psav->PciTag, PCI_CMD_STAT_REG) & SAVAGE_CAP_LIST) {
1683ab47cfaaSmrg	CARD32 cap_ptr, cap_id;
1684ab47cfaaSmrg
1685ab47cfaaSmrg	cap_ptr = pciReadLong(psav->PciTag,
1686ab47cfaaSmrg			      SAVAGE_CAPABILITIES_PTR_PCI_CONFIG)
1687ab47cfaaSmrg	    & SAVAGE_CAP_PTR_MASK;
1688ab47cfaaSmrg
1689ab47cfaaSmrg	while(cap_ptr != SAVAGE_CAP_ID_NULL) {
1690ab47cfaaSmrg	    cap_id = pciReadLong(psav->PciTag, cap_ptr);
1691ab47cfaaSmrg	    if ((cap_id & 0xff) == SAVAGE_CAP_ID_AGP) {
1692ab47cfaaSmrg		psav->IsPCI = FALSE;
1693ab47cfaaSmrg		break;
1694ab47cfaaSmrg	    }
1695ab47cfaaSmrg	    cap_ptr = (cap_id >> 8) & SAVAGE_CAP_PTR_MASK;
1696ab47cfaaSmrg	}
1697ab47cfaaSmrg    }
16988697ee19Smrg#endif
1699ab47cfaaSmrg
1700ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "%s card detected\n",
1701ab47cfaaSmrg	       (psav->IsPCI) ? "PCI" : "AGP");
1702ab47cfaaSmrg
1703ab47cfaaSmrg    if ((s = xf86GetOptValString(psav->Options, OPTION_BUS_TYPE))) {
1704ab47cfaaSmrg	if (strcmp(s, "AGP") == 0) {
1705ab47cfaaSmrg	    if (psav->IsPCI) {
1706ab47cfaaSmrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1707ab47cfaaSmrg			   "BusType AGP not available on PCI card\n");
1708ab47cfaaSmrg	    } else {
1709ab47cfaaSmrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to AGP\n");
1710ab47cfaaSmrg	    }
1711ab47cfaaSmrg	} else if (strcmp(s, "PCI") == 0) {
1712ab47cfaaSmrg	    psav->IsPCI = TRUE;
1713ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "BusType set to PCI\n");
1714ab47cfaaSmrg	} else {
1715ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1716ab47cfaaSmrg		       "Invalid BusType option, using %s DMA\n",
1717ab47cfaaSmrg		       psav->IsPCI ? "PCI" : "AGP");
1718ab47cfaaSmrg	}
1719ab47cfaaSmrg    }
1720ab47cfaaSmrg
1721ab47cfaaSmrg    psav->AgpDMA = !psav->IsPCI;
1722ab47cfaaSmrg    if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_TYPE))) {
1723ab47cfaaSmrg	if (strcmp(s, "AGP") == 0) {
1724ab47cfaaSmrg	    if (psav->IsPCI) {
1725ab47cfaaSmrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1726ab47cfaaSmrg			   "AGP DMA not available on PCI card, using PCI DMA\n");
1727ab47cfaaSmrg	    } else {
1728ab47cfaaSmrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using AGP DMA\n");
1729ab47cfaaSmrg	    }
1730ab47cfaaSmrg	} else if (strcmp(s, "PCI") == 0) {
1731ab47cfaaSmrg	    psav->AgpDMA = FALSE;
1732ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Using PCI DMA\n");
1733ab47cfaaSmrg	} else {
1734ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1735ab47cfaaSmrg		       "Invalid DmaType option, using %s DMA\n",
1736ab47cfaaSmrg		       psav->AgpDMA ? "AGP" : "PCI");
1737ab47cfaaSmrg	}
1738ab47cfaaSmrg    } else {
1739ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT,
1740ab47cfaaSmrg		   "Using %s DMA\n", psav->AgpDMA ? "AGP" : "PCI");
1741ab47cfaaSmrg    }
1742ab47cfaaSmrg
1743ab47cfaaSmrg    psav->CommandDMA = TRUE;
1744ab47cfaaSmrg    psav->VertexDMA = TRUE;
1745ab47cfaaSmrg    from = X_DEFAULT;
1746ab47cfaaSmrg    if ((s = xf86GetOptValString(psav->Options, OPTION_DMA_MODE))) {
1747ab47cfaaSmrg	from = X_CONFIG;
1748ab47cfaaSmrg	if (strcmp(s, "Command") == 0)
1749ab47cfaaSmrg	    psav->VertexDMA = FALSE;
1750ab47cfaaSmrg	else if (strcmp(s, "Vertex") == 0)
1751ab47cfaaSmrg	    psav->CommandDMA = FALSE;
1752ab47cfaaSmrg	else if (strcmp(s, "None") == 0)
1753ab47cfaaSmrg	    psav->VertexDMA = psav->CommandDMA = FALSE;
1754ab47cfaaSmrg	else if (strcmp(s, "Any") != 0) {
1755ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Invalid DmaMode option\n");
1756ab47cfaaSmrg	    from = X_DEFAULT;
1757ab47cfaaSmrg	}
1758ab47cfaaSmrg    }
1759ab47cfaaSmrg    if (psav->CommandDMA && S3_SAVAGE3D_SERIES(psav->Chipset)) {
1760ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO,
1761ab47cfaaSmrg		   "Savage3D/MX/IX does not support command DMA.\n");
1762ab47cfaaSmrg	psav->CommandDMA = FALSE;
1763ab47cfaaSmrg    }
1764ab47cfaaSmrg    if ((psav->CommandDMA || psav->VertexDMA) &&
1765ab47cfaaSmrg	psav->Chipset == S3_SUPERSAVAGE) {
1766ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from == X_CONFIG ? X_WARNING : X_INFO,
1767ab47cfaaSmrg		   "DMA is not supported on SuperSavages.\n");
1768ab47cfaaSmrg	psav->CommandDMA = psav->VertexDMA = FALSE;
1769ab47cfaaSmrg    }
1770ab47cfaaSmrg    if (psav->CommandDMA && psav->VertexDMA)
1771ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from,
1772ab47cfaaSmrg		   "Will try command and vertex DMA mode\n");
1773ab47cfaaSmrg    else if (psav->CommandDMA && !psav->VertexDMA)
1774ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from,
1775ab47cfaaSmrg		   "Will try only command DMA mode\n");
1776ab47cfaaSmrg    else if (!psav->CommandDMA && psav->VertexDMA)
1777ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from,
1778ab47cfaaSmrg		   "Will try only vertex DMA mode\n");
1779ab47cfaaSmrg    else
1780ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from,
1781ab47cfaaSmrg		   "DMA disabled\n");
1782ab47cfaaSmrg
1783ab47cfaaSmrg    if (!psav->IsPCI) {
1784ab47cfaaSmrg	from = X_DEFAULT;
1785ab47cfaaSmrg	psav->agpMode = SAVAGE_DEFAULT_AGP_MODE;
1786ab47cfaaSmrg	/*psav->agpMode = SAVAGE_MAX_AGP_MODE;*/
1787ab47cfaaSmrg	psav->agpSize = 16;
1788ab47cfaaSmrg
1789ab47cfaaSmrg	if (xf86GetOptValInteger(psav->Options,
1790ab47cfaaSmrg				 OPTION_AGP_MODE, &(psav->agpMode))) {
1791ab47cfaaSmrg	    if (psav->agpMode < 1) {
1792ab47cfaaSmrg		psav->agpMode = 1;
1793ab47cfaaSmrg	    }
1794ab47cfaaSmrg	    if (psav->agpMode > SAVAGE_MAX_AGP_MODE) {
1795ab47cfaaSmrg		psav->agpMode = SAVAGE_MAX_AGP_MODE;
1796ab47cfaaSmrg	    }
1797ab47cfaaSmrg	    if ((psav->agpMode > 2) &&
1798ab47cfaaSmrg		(psav->Chipset == S3_SAVAGE3D ||
1799ab47cfaaSmrg		 psav->Chipset == S3_SAVAGE_MX))
1800ab47cfaaSmrg		psav->agpMode = 2; /* old savages only support 2x */
1801ab47cfaaSmrg	    from = X_CONFIG;
1802ab47cfaaSmrg	}
1803ab47cfaaSmrg
1804ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using AGP %dx mode\n",
1805ab47cfaaSmrg		   psav->agpMode);
1806ab47cfaaSmrg
1807ab47cfaaSmrg	from = X_DEFAULT;
1808ab47cfaaSmrg	if (xf86GetOptValInteger(psav->Options,
1809ab47cfaaSmrg				 OPTION_AGP_SIZE, (int *)&(psav->agpSize))) {
1810ab47cfaaSmrg	    switch (psav->agpSize) {
1811ab47cfaaSmrg	    case 4:
1812ab47cfaaSmrg	    case 8:
1813ab47cfaaSmrg	    case 16:
1814ab47cfaaSmrg	    case 32:
1815ab47cfaaSmrg	    case 64:
1816ab47cfaaSmrg	    case 128:
1817ab47cfaaSmrg	    case 256:
1818ab47cfaaSmrg		from = X_CONFIG;
1819ab47cfaaSmrg		break;
1820ab47cfaaSmrg	    default:
1821ab47cfaaSmrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1822ab47cfaaSmrg			   "Illegal AGP size: %d MB, defaulting to 16 MB\n", psav->agpSize);
1823ab47cfaaSmrg		psav->agpSize = 16;
1824ab47cfaaSmrg	    }
1825ab47cfaaSmrg	}
1826ab47cfaaSmrg
1827ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, from,
1828ab47cfaaSmrg		   "Using %d MB AGP aperture\n", psav->agpSize);
1829ab47cfaaSmrg    } else {
1830ab47cfaaSmrg	psav->agpMode = 0;
1831ab47cfaaSmrg	psav->agpSize = 0;
1832ab47cfaaSmrg    }
1833ab47cfaaSmrg
1834ab47cfaaSmrg#endif
1835ab47cfaaSmrg
1836ab47cfaaSmrg    /* we can use Option "DisableTile TRUE" to disable tile mode */
1837ab47cfaaSmrg    psav->bDisableTile = FALSE;
1838ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_TILE,&psav->bDisableTile)) {
1839ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1840ab47cfaaSmrg                   "Option: %s Tile Mode and Program it \n",(psav->bDisableTile?"Disable":"Enable"));
1841ab47cfaaSmrg    }
1842ab47cfaaSmrg
1843ab47cfaaSmrg#ifdef XF86DRI
1844ab47cfaaSmrg    /* disabled by default...doesn't seem to work */
1845ab47cfaaSmrg    psav->bDisableXvMC = TRUE; /* if you want to free up more mem for DRI,etc. */
1846ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_XVMC, &psav->bDisableXvMC)) {
1847ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1848ab47cfaaSmrg                   "Option: %s Hardware XvMC support\n",(psav->bDisableXvMC?"Disable":"Enable"));
1849ab47cfaaSmrg    }
1850ab47cfaaSmrg#endif
1851ab47cfaaSmrg
1852ab47cfaaSmrg    psav->disableCOB = FALSE; /* if you are having problems on savage4+ */
1853ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_DISABLE_COB, &psav->disableCOB)) {
1854ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1855ab47cfaaSmrg                   "Option: %s the COB\n",(psav->disableCOB?"Disable":"Enable"));
1856ab47cfaaSmrg    }
1857ab47cfaaSmrg    if (psav->Chipset == S3_PROSAVAGE ||
1858ab47cfaaSmrg	psav->Chipset == S3_TWISTER   ||
1859ab47cfaaSmrg	psav->Chipset == S3_PROSAVAGEDDR)
1860ab47cfaaSmrg	psav->BCIforXv = TRUE;
1861ab47cfaaSmrg    else
1862ab47cfaaSmrg    	psav->BCIforXv = FALSE; /* use the BCI for Xv */
1863ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_BCI_FOR_XV, &psav->BCIforXv)) {
1864ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1865ab47cfaaSmrg                   "Option: %s use of the BCI for Xv\n",(psav->BCIforXv?"Enable":"Disable"));
1866ab47cfaaSmrg    }
1867ab47cfaaSmrg    psav->dvi = FALSE;
1868ab47cfaaSmrg    if (xf86GetOptValBool(psav->Options, OPTION_DVI, &psav->dvi)) {
1869ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1870ab47cfaaSmrg                   "%s DVI port support (Savage4 only)\n",(psav->dvi?"Force":"Disable"));
1871ab47cfaaSmrg    }
1872ab47cfaaSmrg
1873ab47cfaaSmrg    /* Add more options here. */
1874ab47cfaaSmrg
1875ab47cfaaSmrg
1876ab47cfaaSmrg    psav               = SAVPTR(pScrn);
1877ab47cfaaSmrg    psav->IsSecondary  = FALSE;
1878ab47cfaaSmrg    psav->IsPrimary    = FALSE;
1879ab47cfaaSmrg    psav->pEnt         = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
1880ab47cfaaSmrg
1881ab47cfaaSmrg    if (xf86IsEntityShared(psav->pEnt->index)) {
1882ab47cfaaSmrg	if (xf86IsPrimInitDone(psav->pEnt->index)) {
1883ab47cfaaSmrg
1884ab47cfaaSmrg	    SavageEntPtr pSavageEnt = SavageEntPriv(pScrn);
1885ab47cfaaSmrg
1886ab47cfaaSmrg	    psav->IsSecondary = TRUE;
1887ab47cfaaSmrg	    pSavageEnt->pSecondaryScrn = pScrn;
1888ab47cfaaSmrg	    psav->TvOn = pSavageEnt->TvOn;
1889ab47cfaaSmrg	} else {
1890ab47cfaaSmrg	    SavageEntPtr pSavageEnt = SavageEntPriv(pScrn);
1891ab47cfaaSmrg
1892ab47cfaaSmrg	    xf86SetPrimInitDone(psav->pEnt->index);
1893ab47cfaaSmrg
1894ab47cfaaSmrg	    psav->IsPrimary = TRUE;
1895ab47cfaaSmrg	    pSavageEnt->pPrimaryScrn        = pScrn;
1896ab47cfaaSmrg	    pSavageEnt->TvOn = psav->TvOn;
1897ab47cfaaSmrg	}
1898ab47cfaaSmrg    }
1899ab47cfaaSmrg
1900ab47cfaaSmrg    switch(psav->Chipset) {
1901ab47cfaaSmrg	case S3_SAVAGE_MX:
1902ab47cfaaSmrg	case S3_SUPERSAVAGE:
1903ab47cfaaSmrg	    psav->HasCRTC2 = TRUE;
1904ab47cfaaSmrg	    break;
1905ab47cfaaSmrg        default:
1906ab47cfaaSmrg            psav->HasCRTC2 = FALSE;
1907ab47cfaaSmrg    }
1908ab47cfaaSmrg
1909ab47cfaaSmrg    if ((psav->IsSecondary || psav->IsPrimary) && !psav->UseBIOS) {
1910ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "BIOS currently required for Dualhead mode setting.\n");
1911ab47cfaaSmrg	return FALSE;
1912ab47cfaaSmrg    }
1913ab47cfaaSmrg
1914ab47cfaaSmrg    if (psav->IsSecondary &&
1915ab47cfaaSmrg	(pScrn->bitsPerPixel > 16) &&
1916ab47cfaaSmrg	!psav->NoAccel &&
1917ab47cfaaSmrg	(psav->Chipset == S3_SAVAGE_MX)) {
1918ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No acceleration in Dualhead mode at depth 24\n");
1919ab47cfaaSmrg	return FALSE;
1920ab47cfaaSmrg    }
1921ab47cfaaSmrg
1922ab47cfaaSmrg    /* maybe throw in some more sanity checks here */
1923ab47cfaaSmrg
1924ab47cfaaSmrg    if (!SavageMapMem(pScrn)) {
1925ab47cfaaSmrg	SavageFreeRec(pScrn);
1926ab47cfaaSmrg        vbeFree(psav->pVbe);
1927ab47cfaaSmrg	psav->pVbe = NULL;
1928ab47cfaaSmrg	return FALSE;
1929ab47cfaaSmrg    }
1930ab47cfaaSmrg
1931ab47cfaaSmrg    vgaCRIndex = psav->vgaIOBase + 4;
1932ab47cfaaSmrg    vgaCRReg = psav->vgaIOBase + 5;
1933ab47cfaaSmrg
1934ab47cfaaSmrg    xf86EnableIO();
1935ab47cfaaSmrg    /* unprotect CRTC[0-7] */
1936ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x11);
1937ab47cfaaSmrg    tmp = VGAIN8(vgaCRReg);
1938ab47cfaaSmrg    VGAOUT8(vgaCRReg, tmp & 0x7f);
1939ab47cfaaSmrg
1940ab47cfaaSmrg    /* unlock extended regs */
1941ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0x4838);
1942ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0xa039);
1943ab47cfaaSmrg    VGAOUT16(0x3c4, 0x0608);
1944ab47cfaaSmrg
1945ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x40);
1946ab47cfaaSmrg    tmp = VGAIN8(vgaCRReg);
1947ab47cfaaSmrg    VGAOUT8(vgaCRReg, tmp & ~0x01);
1948ab47cfaaSmrg
1949ab47cfaaSmrg    /* unlock sys regs */
1950ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x38);
1951ab47cfaaSmrg    VGAOUT8(vgaCRReg, 0x48);
1952ab47cfaaSmrg
1953ab47cfaaSmrg    {
1954ab47cfaaSmrg	Gamma zeros = {0.0, 0.0, 0.0};
1955ab47cfaaSmrg
1956ab47cfaaSmrg	if (!xf86SetGamma(pScrn, zeros)) {
1957ab47cfaaSmrg	    vbeFree(psav->pVbe);
1958ab47cfaaSmrg	    psav->pVbe = NULL;
1959ab47cfaaSmrg	    SavageFreeRec(pScrn);
1960ab47cfaaSmrg	    return FALSE;
1961ab47cfaaSmrg	}
1962ab47cfaaSmrg    }
1963ab47cfaaSmrg
1964ab47cfaaSmrg    /* Unlock system registers. */
1965ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0x4838);
1966ab47cfaaSmrg
1967ab47cfaaSmrg    /* Next go on to detect amount of installed ram */
1968ab47cfaaSmrg
1969ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x36);            /* for register CR36 (CONFG_REG1), */
1970ab47cfaaSmrg    config1 = VGAIN8(vgaCRReg);           /* get amount of vram installed */
1971ab47cfaaSmrg
1972ab47cfaaSmrg    /* Compute the amount of video memory and offscreen memory. */
1973ab47cfaaSmrg
1974ab47cfaaSmrg    if (!pScrn->videoRam) {
1975ab47cfaaSmrg	static const unsigned char RamSavage3D[] = { 8, 4, 4, 2 };
1976ab47cfaaSmrg	static unsigned char RamSavage4[] =  { 2, 4, 8, 12, 16, 32, 64, 32 };
1977ab47cfaaSmrg	static const unsigned char RamSavageMX[] = { 2, 8, 4, 16, 8, 16, 4, 16 };
1978ab47cfaaSmrg	static const unsigned char RamSavageNB[] = { 0, 2, 4, 8, 16, 32, 16, 2 };
1979ab47cfaaSmrg
1980ab47cfaaSmrg	switch( psav->Chipset ) {
1981ab47cfaaSmrg	case S3_SAVAGE3D:
1982ab47cfaaSmrg	    pScrn->videoRam = RamSavage3D[ (config1 & 0xC0) >> 6 ] * 1024;
1983ab47cfaaSmrg	    break;
1984ab47cfaaSmrg
1985ab47cfaaSmrg	case S3_SAVAGE4:
1986ab47cfaaSmrg	    /*
1987ab47cfaaSmrg	     * The Savage4 has one ugly special case to consider.  On
1988ab47cfaaSmrg	     * systems with 4 banks of 2Mx32 SDRAM, the BIOS says 4MB
1989ab47cfaaSmrg	     * when it really means 8MB.  Why do it the same when you
1990ab47cfaaSmrg	     * can do it different...
1991ab47cfaaSmrg	     */
1992ab47cfaaSmrg	    VGAOUT8(vgaCRIndex, 0x68);	/* memory control 1 */
1993ab47cfaaSmrg	    if( (VGAIN8(vgaCRReg) & 0xC0) == (0x01 << 6) )
1994ab47cfaaSmrg		RamSavage4[1] = 8;
1995ab47cfaaSmrg
1996ab47cfaaSmrg	    /*FALLTHROUGH*/
1997ab47cfaaSmrg
1998ab47cfaaSmrg	case S3_SAVAGE2000:
1999ab47cfaaSmrg	    pScrn->videoRam = RamSavage4[ (config1 & 0xE0) >> 5 ] * 1024;
2000ab47cfaaSmrg	    break;
2001ab47cfaaSmrg
2002ab47cfaaSmrg	case S3_SAVAGE_MX:
2003ab47cfaaSmrg	case S3_SUPERSAVAGE:
2004ab47cfaaSmrg	    pScrn->videoRam = RamSavageMX[ (config1 & 0x0E) >> 1 ] * 1024;
2005ab47cfaaSmrg	    break;
2006ab47cfaaSmrg
2007ab47cfaaSmrg	case S3_PROSAVAGE:
2008ab47cfaaSmrg	case S3_PROSAVAGEDDR:
2009ab47cfaaSmrg	case S3_TWISTER:
2010ab47cfaaSmrg	    pScrn->videoRam = RamSavageNB[ (config1 & 0xE0) >> 5 ] * 1024;
2011ab47cfaaSmrg	    break;
2012ab47cfaaSmrg
2013ab47cfaaSmrg	default:
2014ab47cfaaSmrg	    /* How did we get here? */
2015ab47cfaaSmrg	    pScrn->videoRam = 0;
2016ab47cfaaSmrg	    break;
2017ab47cfaaSmrg	}
2018ab47cfaaSmrg
2019ab47cfaaSmrg	psav->videoRambytes = pScrn->videoRam * 1024;
2020ab47cfaaSmrg
2021ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2022ab47cfaaSmrg		"probed videoram:  %dk\n",
2023ab47cfaaSmrg		pScrn->videoRam);
2024ab47cfaaSmrg    } else {
2025ab47cfaaSmrg	psav->videoRambytes = pScrn->videoRam * 1024;
2026ab47cfaaSmrg
2027ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
2028ab47cfaaSmrg	       "videoram =  %dk\n",
2029ab47cfaaSmrg		pScrn->videoRam);
2030ab47cfaaSmrg    }
2031ab47cfaaSmrg
2032ab47cfaaSmrg    /* Get video RAM */
2033ab47cfaaSmrg    if( !pScrn->videoRam && psav->pVbe )
2034ab47cfaaSmrg    {
2035ab47cfaaSmrg        /* If VBE is available, ask it about onboard memory. */
2036ab47cfaaSmrg
2037ab47cfaaSmrg	VbeInfoBlock* vib;
2038ab47cfaaSmrg
2039ab47cfaaSmrg	vib = VBEGetVBEInfo( psav->pVbe );
2040ab47cfaaSmrg	pScrn->videoRam = vib->TotalMemory * 64;
2041ab47cfaaSmrg	VBEFreeVBEInfo( vib );
2042ab47cfaaSmrg
2043ab47cfaaSmrg	/* VBE often cuts 64k off of the RAM total. */
2044ab47cfaaSmrg
2045ab47cfaaSmrg	if( pScrn->videoRam & 64 )
2046ab47cfaaSmrg	    pScrn->videoRam += 64;
2047ab47cfaaSmrg
2048ab47cfaaSmrg	psav->videoRambytes = pScrn->videoRam * 1024;
2049ab47cfaaSmrg    }
2050ab47cfaaSmrg
2051ab47cfaaSmrg
2052ab47cfaaSmrg    /*
2053ab47cfaaSmrg     * If we're running with acceleration, compute the command overflow
2054ab47cfaaSmrg     * buffer location.  The command overflow buffer must END at a
2055ab47cfaaSmrg     * 4MB boundary; for all practical purposes, that means the very
2056ab47cfaaSmrg     * end of the frame buffer.
2057ab47cfaaSmrg     */
2058ab47cfaaSmrg    if (psav->NoAccel) {
2059ab47cfaaSmrg        psav->cobIndex = 0;
2060ab47cfaaSmrg        psav->cobSize = 0;
2061ab47cfaaSmrg    }
2062ab47cfaaSmrg    else if( ((S3_SAVAGE4_SERIES(psav->Chipset)) ||
2063ab47cfaaSmrg             (S3_SUPERSAVAGE == psav->Chipset)) && psav->disableCOB ) {
2064ab47cfaaSmrg        /*
2065ab47cfaaSmrg         * The Savage4 and ProSavage have COB coherency bugs which render
2066ab47cfaaSmrg         * the buffer useless.
2067ab47cfaaSmrg         */
2068ab47cfaaSmrg	/*
2069ab47cfaaSmrg        psav->cobIndex = 2;
2070ab47cfaaSmrg        psav->cobSize = 0x8000 << psav->cobIndex;
2071ab47cfaaSmrg	*/
2072ab47cfaaSmrg        psav->cobIndex = 0;
2073ab47cfaaSmrg        psav->cobSize = 0;
2074ab47cfaaSmrg	psav->bciThresholdHi = 32;
2075ab47cfaaSmrg	psav->bciThresholdLo = 0;
2076ab47cfaaSmrg    } else {
2077ab47cfaaSmrg        /* We use 128kB for the COB on all other chips. */
2078ab47cfaaSmrg        psav->cobSize = 0x20000;
2079ab47cfaaSmrg	if (S3_SAVAGE3D_SERIES(psav->Chipset) ||
2080ab47cfaaSmrg	    psav->Chipset == S3_SAVAGE2000) {
2081ab47cfaaSmrg	    psav->cobIndex = 7; /* rev.A savage4 apparently also uses 7 */
2082ab47cfaaSmrg	} else {
2083ab47cfaaSmrg	    psav->cobIndex = 2;
2084ab47cfaaSmrg	}
2085ab47cfaaSmrg	/* max command size: 2560 entries */
2086ab47cfaaSmrg	psav->bciThresholdHi = psav->cobSize/4 + 32 - 2560;
2087ab47cfaaSmrg	psav->bciThresholdLo = psav->bciThresholdHi - 2560;
2088ab47cfaaSmrg    }
2089ab47cfaaSmrg
2090ab47cfaaSmrg    /* align cob to 128k */
2091ab47cfaaSmrg    psav->cobOffset = (psav->videoRambytes - psav->cobSize) & ~0x1ffff;
2092ab47cfaaSmrg
2093ab47cfaaSmrg    /* The cursor must be aligned on a 4k boundary. */
2094ab47cfaaSmrg    psav->CursorKByte = (psav->cobOffset >> 10) - 4;
2095ab47cfaaSmrg    psav->endfb = (psav->CursorKByte << 10) - 1;
2096ab47cfaaSmrg
2097ab47cfaaSmrg    if (psav->IsPrimary) {
2098ab47cfaaSmrg        pScrn->videoRam /= 2;
2099ab47cfaaSmrg	psav->videoRambytes = pScrn->videoRam * 1024;
2100ab47cfaaSmrg	psav->CursorKByte = (psav->videoRambytes >> 10) - 4;
2101ab47cfaaSmrg	psav->endfb = (psav->CursorKByte << 10) - 1;
2102ab47cfaaSmrg	psav->videoRambytes *= 2;
2103ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2104ab47cfaaSmrg		"Using %dk of videoram for primary head\n",
2105ab47cfaaSmrg		pScrn->videoRam);
2106ab47cfaaSmrg    }
2107ab47cfaaSmrg
2108ab47cfaaSmrg    if(psav->IsSecondary)
2109ab47cfaaSmrg    {
2110ab47cfaaSmrg        pScrn->videoRam /= 2;
2111ab47cfaaSmrg	/*psav->videoRambytes = pScrn->videoRam * 1024;*/
2112ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2113ab47cfaaSmrg		"Using %dk of videoram for secondary head\n",
2114ab47cfaaSmrg		pScrn->videoRam);
2115ab47cfaaSmrg    }
2116ab47cfaaSmrg
2117ab47cfaaSmrg    pScrn->fbOffset = (psav->IsSecondary)
2118ab47cfaaSmrg      ? pScrn->videoRam * 1024 : 0;
2119ab47cfaaSmrg
2120ab47cfaaSmrg    /* reset graphics engine to avoid memory corruption */
2121ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2122ab47cfaaSmrg    cr66 = VGAIN8(vgaCRReg);
2123ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66 | 0x02);
2124ab47cfaaSmrg    usleep(10000);
2125ab47cfaaSmrg
2126ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2127ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66 & ~0x02);	/* clear reset flag */
2128ab47cfaaSmrg    usleep(10000);
2129ab47cfaaSmrg
2130ab47cfaaSmrg    /* Set status word positions based on chip type. */
2131ab47cfaaSmrg    SavageInitStatus(pScrn);
2132ab47cfaaSmrg
2133ab47cfaaSmrg    /* check for DVI/flat panel */
2134ab47cfaaSmrg    dvi = FALSE;
2135ab47cfaaSmrg    if (psav->Chipset == S3_SAVAGE4) {
2136ab47cfaaSmrg	unsigned char sr30 = 0x00;
2137ab47cfaaSmrg	VGAOUT8(0x3c4, 0x30);
2138ab47cfaaSmrg	/* clear bit 1 */
2139ab47cfaaSmrg	VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x02);
2140ab47cfaaSmrg    	sr30 = VGAIN8(0x3c5);
2141ab47cfaaSmrg    	if (sr30 & 0x02 /*0x04 */) {
2142ab47cfaaSmrg            dvi = TRUE;
2143ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Digital Flat Panel Detected\n");
2144ab47cfaaSmrg	}
2145ab47cfaaSmrg    }
2146ab47cfaaSmrg
2147ab47cfaaSmrg    if( (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
2148ab47cfaaSmrg	S3_MOBILE_TWISTER_SERIES(psav->Chipset)) && !psav->CrtOnly ) {
2149ab47cfaaSmrg	psav->DisplayType = MT_LCD;
2150ab47cfaaSmrg    } else if (dvi || ((psav->Chipset == S3_SAVAGE4) && psav->dvi)) {
2151ab47cfaaSmrg	psav->DisplayType = MT_DFP;
2152ab47cfaaSmrg    } else {
2153ab47cfaaSmrg	psav->DisplayType = MT_CRT;
2154ab47cfaaSmrg    }
2155ab47cfaaSmrg
2156ab47cfaaSmrg    if (psav->IsSecondary)
2157ab47cfaaSmrg	psav->DisplayType = MT_CRT;
2158ab47cfaaSmrg
2159ab47cfaaSmrg    /* Do the DDC dance. */
2160ab47cfaaSmrg    SavageDoDDC(pScrn);
2161ab47cfaaSmrg
2162ab47cfaaSmrg    /* set up ramdac max clock - might be altered by SavageGetPanelInfo */
2163ab47cfaaSmrg    if (pScrn->bitsPerPixel >= 24)
2164ab47cfaaSmrg        psav->maxClock = 220000;
2165ab47cfaaSmrg    else
2166ab47cfaaSmrg        psav->maxClock = 250000;
2167ab47cfaaSmrg
2168ab47cfaaSmrg    /* detect current mclk */
2169ab47cfaaSmrg    VGAOUT8(0x3c4, 0x08);
2170ab47cfaaSmrg    sr8 = VGAIN8(0x3c5);
2171ab47cfaaSmrg    VGAOUT8(0x3c5, 0x06);
2172ab47cfaaSmrg    VGAOUT8(0x3c4, 0x10);
2173ab47cfaaSmrg    n = VGAIN8(0x3c5);
2174ab47cfaaSmrg    VGAOUT8(0x3c4, 0x11);
2175ab47cfaaSmrg    m = VGAIN8(0x3c5);
2176ab47cfaaSmrg    VGAOUT8(0x3c4, 0x08);
2177ab47cfaaSmrg    VGAOUT8(0x3c5, sr8);
2178ab47cfaaSmrg    m &= 0x7f;
2179ab47cfaaSmrg    n1 = n & 0x1f;
2180ab47cfaaSmrg    n2 = (n >> 5) & 0x03;
2181ab47cfaaSmrg    mclk = ((1431818 * (m+2)) / (n1+2) / (1 << n2) + 50) / 100;
2182ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Detected current MCLK value of %1.3f MHz\n",
2183ab47cfaaSmrg	       mclk / 1000.0);
2184ab47cfaaSmrg
2185ab47cfaaSmrg    pScrn->maxHValue = 2048 << 3;	/* 11 bits of h_total 8-pixel units */
2186ab47cfaaSmrg    pScrn->maxVValue = 2048;		/* 11 bits of v_total */
2187ab47cfaaSmrg    pScrn->virtualX = pScrn->display->virtualX;
2188ab47cfaaSmrg    pScrn->virtualY = pScrn->display->virtualY;
2189ab47cfaaSmrg
2190ab47cfaaSmrg    /* Check LCD panel information */
2191ab47cfaaSmrg
2192ab47cfaaSmrg    if(psav->DisplayType == MT_LCD)
2193ab47cfaaSmrg    {
2194ab47cfaaSmrg	SavageGetPanelInfo(pScrn);
2195ab47cfaaSmrg	SavageAddPanelMode(pScrn);
2196ab47cfaaSmrg    }
2197ab47cfaaSmrg
2198ab47cfaaSmrg#if 0
2199ab47cfaaSmrg    if (psav->CrtOnly && !psav->UseBIOS) {
2200ab47cfaaSmrg	VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
2201ab47cfaaSmrg	VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10); /* disable FP */
2202ab47cfaaSmrg        if (S3_SAVAGE_MOBILE_SERIES(psav->Chipset) /*||
2203ab47cfaaSmrg	    S3_MOBILE_TWISTER_SERIES(psav->Chipset)*/) { /* not sure this works on mobile prosavage */
2204ab47cfaaSmrg		VGAOUT8(0x3c4, 0x31);
2205ab47cfaaSmrg		VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x04); /* make sure crtc1 is crt source */
2206ab47cfaaSmrg    	}
2207ab47cfaaSmrg    }
2208ab47cfaaSmrg#endif
2209ab47cfaaSmrg
2210ab47cfaaSmrg    if( psav->UseBIOS )
2211ab47cfaaSmrg    {
2212ab47cfaaSmrg	/* Go probe the BIOS for all the modes and refreshes at this depth. */
2213ab47cfaaSmrg
2214ab47cfaaSmrg	if( psav->ModeTable )
2215ab47cfaaSmrg	{
2216ab47cfaaSmrg	    SavageFreeBIOSModeTable( psav, &psav->ModeTable );
2217ab47cfaaSmrg	}
2218ab47cfaaSmrg
2219ab47cfaaSmrg	psav->ModeTable = SavageGetBIOSModeTable( psav, psav->primStreamBpp );
2220ab47cfaaSmrg
2221ab47cfaaSmrg	if( !psav->ModeTable || !psav->ModeTable->NumModes ) {
2222ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2223ab47cfaaSmrg		       "Failed to fetch any BIOS modes.  Disabling BIOS.\n");
2224ab47cfaaSmrg	    psav->UseBIOS = FALSE;
2225ab47cfaaSmrg	}
2226ab47cfaaSmrg	else
2227ab47cfaaSmrg	/*if( xf86Verbose )*/
2228ab47cfaaSmrg	{
2229ab47cfaaSmrg	    SavageModeEntryPtr pmt;
2230ab47cfaaSmrg
2231ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2232ab47cfaaSmrg		       "Found %d modes at this depth:\n",
2233ab47cfaaSmrg		       psav->ModeTable->NumModes);
2234ab47cfaaSmrg
2235ab47cfaaSmrg	    for(
2236ab47cfaaSmrg		i = 0, pmt = psav->ModeTable->Modes;
2237ab47cfaaSmrg		i < psav->ModeTable->NumModes;
2238ab47cfaaSmrg		i++, pmt++ )
2239ab47cfaaSmrg	    {
2240ab47cfaaSmrg		int j;
2241ab47cfaaSmrg		ErrorF( "    [%03x] %d x %d",
2242ab47cfaaSmrg			pmt->VesaMode, pmt->Width, pmt->Height );
2243ab47cfaaSmrg		for( j = 0; j < pmt->RefreshCount; j++ )
2244ab47cfaaSmrg		{
2245ab47cfaaSmrg		    ErrorF( ", %dHz", pmt->RefreshRate[j] );
2246ab47cfaaSmrg		}
2247ab47cfaaSmrg		ErrorF( "\n");
2248ab47cfaaSmrg	    }
2249ab47cfaaSmrg	}
2250ab47cfaaSmrg    }
2251ab47cfaaSmrg
2252ab47cfaaSmrg    clockRanges = xnfalloc(sizeof(ClockRange));
2253ab47cfaaSmrg    clockRanges->next = NULL;
2254ab47cfaaSmrg    clockRanges->minClock = 10000;
2255ab47cfaaSmrg    clockRanges->maxClock = psav->maxClock;
2256ab47cfaaSmrg    clockRanges->clockIndex = -1;
2257ab47cfaaSmrg    clockRanges->interlaceAllowed = TRUE;
2258ab47cfaaSmrg    clockRanges->doubleScanAllowed = TRUE;
2259ab47cfaaSmrg    clockRanges->ClockDivFactor = 1.0;
2260ab47cfaaSmrg    clockRanges->ClockMulFactor = 1.0;
2261ab47cfaaSmrg
2262ab47cfaaSmrg    i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2263ab47cfaaSmrg			  pScrn->display->modes, clockRanges, NULL,
2264ab47cfaaSmrg			  256, 2048, 16 * pScrn->bitsPerPixel,
2265ab47cfaaSmrg			  128, 2048,
2266ab47cfaaSmrg			  pScrn->virtualX, pScrn->virtualY,
2267ab47cfaaSmrg			  psav->videoRambytes, LOOKUP_BEST_REFRESH);
2268ab47cfaaSmrg
2269ab47cfaaSmrg    if (i == -1) {
2270ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86ValidateModes failure\n");
2271ab47cfaaSmrg	SavageFreeRec(pScrn);
2272ab47cfaaSmrg	vbeFree(psav->pVbe);
2273ab47cfaaSmrg	psav->pVbe = NULL;
2274ab47cfaaSmrg	return FALSE;
2275ab47cfaaSmrg    }
2276ab47cfaaSmrg
2277ab47cfaaSmrg    xf86PruneDriverModes(pScrn);
2278ab47cfaaSmrg
2279ab47cfaaSmrg    if (i == 0 || pScrn->modes == NULL) {
2280ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
2281ab47cfaaSmrg	SavageFreeRec(pScrn);
2282ab47cfaaSmrg	vbeFree(psav->pVbe);
2283ab47cfaaSmrg	psav->pVbe = NULL;
2284ab47cfaaSmrg	return FALSE;
2285ab47cfaaSmrg    }
2286ab47cfaaSmrg
2287ab47cfaaSmrg    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
2288ab47cfaaSmrg    pScrn->currentMode = pScrn->modes;
2289ab47cfaaSmrg    xf86PrintModes(pScrn);
2290ab47cfaaSmrg    xf86SetDpi(pScrn, 0, 0);
2291ab47cfaaSmrg
2292ab47cfaaSmrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
2293ab47cfaaSmrg	SavageFreeRec(pScrn);
2294ab47cfaaSmrg	vbeFree(psav->pVbe);
2295ab47cfaaSmrg	psav->pVbe = NULL;
2296ab47cfaaSmrg	return FALSE;
2297ab47cfaaSmrg    }
2298ab47cfaaSmrg
2299ab47cfaaSmrg    xf86LoaderReqSymLists(fbSymbols, NULL);
2300ab47cfaaSmrg
2301ab47cfaaSmrg    if( !psav->NoAccel ) {
2302ab47cfaaSmrg
2303ab47cfaaSmrg        char *modName = NULL;
2304ab47cfaaSmrg        const char **symNames = NULL;
2305ab47cfaaSmrg
2306ab47cfaaSmrg	if (psav->useEXA) {
2307ab47cfaaSmrg	    modName = "exa";
2308ab47cfaaSmrg	    symNames = exaSymbols;
2309ab47cfaaSmrg	    XF86ModReqInfo req;
2310ab47cfaaSmrg	    int errmaj, errmin;
2311ab47cfaaSmrg	    memset(&req, 0, sizeof(req));
2312ab47cfaaSmrg	    req.majorversion = 2;
2313ab47cfaaSmrg	    req.minorversion = 0;
2314ab47cfaaSmrg
2315ab47cfaaSmrg	    if( !LoadSubModule(pScrn->module, modName,
2316ab47cfaaSmrg		NULL, NULL, NULL, &req, &errmaj, &errmin) ) {
2317ab47cfaaSmrg		LoaderErrorMsg(NULL, modName, errmaj, errmin);
2318ab47cfaaSmrg	    	SavageFreeRec(pScrn);
2319ab47cfaaSmrg	    	vbeFree(psav->pVbe);
2320ab47cfaaSmrg	    	psav->pVbe = NULL;
2321ab47cfaaSmrg	    	return FALSE;
2322ab47cfaaSmrg	    }
2323ab47cfaaSmrg	} else {
2324ab47cfaaSmrg	    modName = "xaa";
2325ab47cfaaSmrg	    symNames = xaaSymbols;
2326ab47cfaaSmrg	    if( !xf86LoadSubModule(pScrn, modName) ) {
2327ab47cfaaSmrg	    	SavageFreeRec(pScrn);
2328ab47cfaaSmrg	    	vbeFree(psav->pVbe);
2329ab47cfaaSmrg	    	psav->pVbe = NULL;
2330ab47cfaaSmrg	    	return FALSE;
2331ab47cfaaSmrg	    }
2332ab47cfaaSmrg	}
2333ab47cfaaSmrg
2334ab47cfaaSmrg	xf86LoaderReqSymLists(symNames, NULL );
2335ab47cfaaSmrg
2336ab47cfaaSmrg    }
2337ab47cfaaSmrg
2338ab47cfaaSmrg    if (psav->hwcursor) {
2339ab47cfaaSmrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
2340ab47cfaaSmrg	    SavageFreeRec(pScrn);
2341ab47cfaaSmrg	    vbeFree(psav->pVbe);
2342ab47cfaaSmrg	    psav->pVbe = NULL;
2343ab47cfaaSmrg	    return FALSE;
2344ab47cfaaSmrg	}
2345ab47cfaaSmrg	xf86LoaderReqSymLists(ramdacSymbols, NULL);
2346ab47cfaaSmrg    }
2347ab47cfaaSmrg
2348ab47cfaaSmrg    if (psav->shadowFB) {
2349ab47cfaaSmrg	if (!xf86LoadSubModule(pScrn, "shadowfb")) {
2350ab47cfaaSmrg	    SavageFreeRec(pScrn);
2351ab47cfaaSmrg	    vbeFree(psav->pVbe);
2352ab47cfaaSmrg	    psav->pVbe = NULL;
2353ab47cfaaSmrg	    return FALSE;
2354ab47cfaaSmrg	}
2355ab47cfaaSmrg	xf86LoaderReqSymLists(shadowSymbols, NULL);
2356ab47cfaaSmrg    }
2357ab47cfaaSmrg    vbeFree(psav->pVbe);
2358ab47cfaaSmrg
2359ab47cfaaSmrg    psav->pVbe = NULL;
2360ab47cfaaSmrg
2361ab47cfaaSmrg    return TRUE;
2362ab47cfaaSmrg}
2363ab47cfaaSmrg
2364ab47cfaaSmrg
2365ab47cfaaSmrgstatic Bool SavageEnterVT(int scrnIndex, int flags)
2366ab47cfaaSmrg{
2367ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2368ab47cfaaSmrg#ifdef XF86DRI
2369ab47cfaaSmrg    SavagePtr psav= SAVPTR(pScrn);
2370ab47cfaaSmrg    ScreenPtr pScreen;
2371ab47cfaaSmrg    SAVAGESAREAPrivPtr pSAREAPriv;
2372ab47cfaaSmrg#endif
2373ab47cfaaSmrg
2374ab47cfaaSmrg    TRACE(("SavageEnterVT(%d)\n", flags));
2375ab47cfaaSmrg
2376ab47cfaaSmrg    gpScrn = pScrn;
2377ab47cfaaSmrg    SavageEnableMMIO(pScrn);
2378ab47cfaaSmrg
2379ab47cfaaSmrg#ifdef XF86DRI
2380ab47cfaaSmrg    if (psav->directRenderingEnabled) {
2381ab47cfaaSmrg        pScreen = screenInfo.screens[scrnIndex];
2382ab47cfaaSmrg	pSAREAPriv = (SAVAGESAREAPrivPtr)DRIGetSAREAPrivate(pScreen);
2383ab47cfaaSmrg	/* Assume that 3D state was clobbered, invalidate it by
2384ab47cfaaSmrg	 * changing ctxOwner in the sarea. */
2385ab47cfaaSmrg	pSAREAPriv->ctxOwner = DRIGetContext(pScreen);
2386ab47cfaaSmrg        DRIUnlock(pScreen);
2387ab47cfaaSmrg        psav->LockHeld = 0;
2388ab47cfaaSmrg    }
2389ab47cfaaSmrg#endif
2390ab47cfaaSmrg    if (!SAVPTR(pScrn)->IsSecondary)
2391ab47cfaaSmrg    	SavageSave(pScrn);
2392ab47cfaaSmrg    if(SavageModeInit(pScrn, pScrn->currentMode)) {
2393ab47cfaaSmrg	/* some BIOSes seem to enable HW cursor on PM resume */
2394ab47cfaaSmrg	if (!SAVPTR(pScrn)->hwc_on)
2395ab47cfaaSmrg	    SavageHideCursor( pScrn );
2396ab47cfaaSmrg	return TRUE;
2397ab47cfaaSmrg    }
2398ab47cfaaSmrg
2399ab47cfaaSmrg    return FALSE;
2400ab47cfaaSmrg}
2401ab47cfaaSmrg
2402ab47cfaaSmrg
2403ab47cfaaSmrgstatic void SavageLeaveVT(int scrnIndex, int flags)
2404ab47cfaaSmrg{
2405ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
2406ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2407ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
2408ab47cfaaSmrg    vgaRegPtr vgaSavePtr = &hwp->SavedReg;
2409ab47cfaaSmrg    SavageRegPtr SavageSavePtr = &psav->SavedReg;
2410ab47cfaaSmrg#ifdef XF86DRI
2411ab47cfaaSmrg    ScreenPtr pScreen;
2412ab47cfaaSmrg#endif
2413ab47cfaaSmrg
2414ab47cfaaSmrg    TRACE(("SavageLeaveVT(%d)\n", flags));
2415ab47cfaaSmrg    gpScrn = pScrn;
2416ab47cfaaSmrg
2417ab47cfaaSmrg#ifdef XF86DRI
2418ab47cfaaSmrg    if (psav->directRenderingEnabled) {
2419ab47cfaaSmrg        pScreen = screenInfo.screens[scrnIndex];
2420ab47cfaaSmrg        DRILock(pScreen, 0);
2421ab47cfaaSmrg        psav->LockHeld = 1;
2422ab47cfaaSmrg    }
2423ab47cfaaSmrg#endif
2424ab47cfaaSmrg    if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON))
2425ab47cfaaSmrg        SavageStreamsOff(pScrn);
2426ab47cfaaSmrg    SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE);
2427ab47cfaaSmrg    SavageResetStreams(pScrn);
2428ab47cfaaSmrg    SavageDisableMMIO(pScrn);
2429ab47cfaaSmrg
2430ab47cfaaSmrg}
2431ab47cfaaSmrg
2432ab47cfaaSmrg
2433ab47cfaaSmrgstatic void SavageSave(ScrnInfoPtr pScrn)
2434ab47cfaaSmrg{
2435ab47cfaaSmrg    unsigned char cr3a, cr53, cr66;
2436ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2437ab47cfaaSmrg    vgaRegPtr vgaSavePtr = &hwp->SavedReg;
2438ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
2439ab47cfaaSmrg    SavageRegPtr save = &psav->SavedReg;
2440ab47cfaaSmrg    unsigned short vgaCRReg = psav->vgaIOBase + 5;
2441ab47cfaaSmrg    unsigned short vgaCRIndex = psav->vgaIOBase + 4;
2442ab47cfaaSmrg
2443ab47cfaaSmrg    TRACE(("SavageSave()\n"));
2444ab47cfaaSmrg
2445ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0x4838);
2446ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0xa039);
2447ab47cfaaSmrg    VGAOUT16(0x3c4, 0x0608);
2448ab47cfaaSmrg
2449ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2450ab47cfaaSmrg    cr66 = VGAIN8(vgaCRReg);
2451ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66 | 0x80);
2452ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2453ab47cfaaSmrg    cr3a = VGAIN8(vgaCRReg);
2454ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a | 0x80);
2455ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x53);
2456ab47cfaaSmrg    cr53 = VGAIN8(vgaCRReg);
2457ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr53 & 0x7f);
2458ab47cfaaSmrg
2459ab47cfaaSmrg    if (xf86IsPrimaryPci(psav->PciInfo))
2460ab47cfaaSmrg	vgaHWSave(pScrn, vgaSavePtr, VGA_SR_ALL);
2461ab47cfaaSmrg    else
2462ab47cfaaSmrg	vgaHWSave(pScrn, vgaSavePtr, VGA_SR_MODE);
2463ab47cfaaSmrg
2464ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2465ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66);
2466ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2467ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a);
2468ab47cfaaSmrg
2469ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2470ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66);
2471ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2472ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a);
2473ab47cfaaSmrg
2474ab47cfaaSmrg    /* unlock extended seq regs */
2475ab47cfaaSmrg    VGAOUT8(0x3c4, 0x08);
2476ab47cfaaSmrg    save->SR08 = VGAIN8(0x3c5);
2477ab47cfaaSmrg    VGAOUT8(0x3c5, 0x06);
2478ab47cfaaSmrg
2479ab47cfaaSmrg    /* now save all the extended regs we need */
2480ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x31);
2481ab47cfaaSmrg    save->CR31 = VGAIN8(vgaCRReg);
2482ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x32);
2483ab47cfaaSmrg    save->CR32 = VGAIN8(vgaCRReg);
2484ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x34);
2485ab47cfaaSmrg    save->CR34 = VGAIN8(vgaCRReg);
2486ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x36);
2487ab47cfaaSmrg    save->CR36 = VGAIN8(vgaCRReg);
2488ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2489ab47cfaaSmrg    save->CR3A = VGAIN8(vgaCRReg);
2490ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x40);
2491ab47cfaaSmrg    save->CR40 = VGAIN8(vgaCRReg);
2492ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x42);
2493ab47cfaaSmrg    save->CR42 = VGAIN8(vgaCRReg);
2494ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x45);
2495ab47cfaaSmrg    save->CR45 = VGAIN8(vgaCRReg);
2496ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x50);
2497ab47cfaaSmrg    save->CR50 = VGAIN8(vgaCRReg);
2498ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x51);
2499ab47cfaaSmrg    save->CR51 = VGAIN8(vgaCRReg);
2500ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x53);
2501ab47cfaaSmrg    save->CR53 = VGAIN8(vgaCRReg);
2502ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x58);
2503ab47cfaaSmrg    save->CR58 = VGAIN8(vgaCRReg);
2504ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x60);
2505ab47cfaaSmrg    save->CR60 = VGAIN8(vgaCRReg);
2506ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2507ab47cfaaSmrg    save->CR66 = VGAIN8(vgaCRReg);
2508ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x67);
2509ab47cfaaSmrg    save->CR67 = VGAIN8(vgaCRReg);
2510ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x68);
2511ab47cfaaSmrg    save->CR68 = VGAIN8(vgaCRReg);
2512ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x69);
2513ab47cfaaSmrg    save->CR69 = VGAIN8(vgaCRReg);
2514ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x6f);
2515ab47cfaaSmrg    save->CR6F = VGAIN8(vgaCRReg);
2516ab47cfaaSmrg
2517ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x33);
2518ab47cfaaSmrg    save->CR33 = VGAIN8(vgaCRReg);
2519ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x86);
2520ab47cfaaSmrg    save->CR86 = VGAIN8(vgaCRReg);
2521ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x88);
2522ab47cfaaSmrg    save->CR88 = VGAIN8(vgaCRReg);
2523ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x90);
2524ab47cfaaSmrg    save->CR90 = VGAIN8(vgaCRReg);
2525ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x91);
2526ab47cfaaSmrg    save->CR91 = VGAIN8(vgaCRReg);
2527ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0xb0);
2528ab47cfaaSmrg    save->CRB0 = VGAIN8(vgaCRReg) | 0x80;
2529ab47cfaaSmrg
2530ab47cfaaSmrg    /* extended mode timing regs */
2531ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3b);
2532ab47cfaaSmrg    save->CR3B = VGAIN8(vgaCRReg);
2533ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3c);
2534ab47cfaaSmrg    save->CR3C = VGAIN8(vgaCRReg);
2535ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x43);
2536ab47cfaaSmrg    save->CR43 = VGAIN8(vgaCRReg);
2537ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x5d);
2538ab47cfaaSmrg    save->CR5D = VGAIN8(vgaCRReg);
2539ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x5e);
2540ab47cfaaSmrg    save->CR5E = VGAIN8(vgaCRReg);
2541ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x65);
2542ab47cfaaSmrg    save->CR65 = VGAIN8(vgaCRReg);
2543ab47cfaaSmrg
2544ab47cfaaSmrg    /* save seq extended regs for DCLK PLL programming */
2545ab47cfaaSmrg    VGAOUT8(0x3c4, 0x0e);
2546ab47cfaaSmrg    save->SR0E = VGAIN8(0x3c5);
2547ab47cfaaSmrg    VGAOUT8(0x3c4, 0x0f);
2548ab47cfaaSmrg    save->SR0F = VGAIN8(0x3c5);
2549ab47cfaaSmrg    VGAOUT8(0x3c4, 0x10);
2550ab47cfaaSmrg    save->SR10 = VGAIN8(0x3c5);
2551ab47cfaaSmrg    VGAOUT8(0x3c4, 0x11);
2552ab47cfaaSmrg    save->SR11 = VGAIN8(0x3c5);
2553ab47cfaaSmrg    VGAOUT8(0x3c4, 0x12);
2554ab47cfaaSmrg    save->SR12 = VGAIN8(0x3c5);
2555ab47cfaaSmrg    VGAOUT8(0x3c4, 0x13);
2556ab47cfaaSmrg    save->SR13 = VGAIN8(0x3c5);
2557ab47cfaaSmrg    VGAOUT8(0x3c4, 0x29);
2558ab47cfaaSmrg    save->SR29 = VGAIN8(0x3c5);
2559ab47cfaaSmrg
2560ab47cfaaSmrg    VGAOUT8(0x3c4, 0x15);
2561ab47cfaaSmrg    save->SR15 = VGAIN8(0x3c5);
2562ab47cfaaSmrg    VGAOUT8(0x3c4, 0x30);
2563ab47cfaaSmrg    save->SR30 = VGAIN8(0x3c5);
2564ab47cfaaSmrg    VGAOUT8(0x3c4, 0x18);
2565ab47cfaaSmrg    save->SR18 = VGAIN8(0x3c5);
2566ab47cfaaSmrg    VGAOUT8(0x3c4, 0x1b);
2567ab47cfaaSmrg    save->SR1B = VGAIN8(0x3c5);
2568ab47cfaaSmrg
2569ab47cfaaSmrg    /* Save flat panel expansion registers. */
2570ab47cfaaSmrg
2571ab47cfaaSmrg    if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
2572ab47cfaaSmrg	S3_MOBILE_TWISTER_SERIES(psav->Chipset)) {
2573ab47cfaaSmrg	int i;
2574ab47cfaaSmrg	for( i = 0; i < 8; i++ ) {
2575ab47cfaaSmrg	    VGAOUT8(0x3c4, 0x54+i);
2576ab47cfaaSmrg	    save->SR54[i] = VGAIN8(0x3c5);
2577ab47cfaaSmrg	}
2578ab47cfaaSmrg    }
2579ab47cfaaSmrg
2580ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2581ab47cfaaSmrg    cr66 = VGAIN8(vgaCRReg);
2582ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66 | 0x80);
2583ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2584ab47cfaaSmrg    cr3a = VGAIN8(vgaCRReg);
2585ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a | 0x80);
2586ab47cfaaSmrg
2587ab47cfaaSmrg    /* now save MIU regs */
2588ab47cfaaSmrg    if( ! S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) {
2589ab47cfaaSmrg	save->MMPR0 = INREG(FIFO_CONTROL_REG);
2590ab47cfaaSmrg	save->MMPR1 = INREG(MIU_CONTROL_REG);
2591ab47cfaaSmrg	save->MMPR2 = INREG(STREAMS_TIMEOUT_REG);
2592ab47cfaaSmrg	save->MMPR3 = INREG(MISC_TIMEOUT_REG);
2593ab47cfaaSmrg    }
2594ab47cfaaSmrg
2595ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2596ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a);
2597ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2598ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66);
2599ab47cfaaSmrg
2600ab47cfaaSmrg    if (!psav->ModeStructInit) {
2601ab47cfaaSmrg	vgaHWCopyReg(&hwp->ModeReg, vgaSavePtr);
2602ab47cfaaSmrg	memcpy(&psav->ModeReg, save, sizeof(SavageRegRec));
2603ab47cfaaSmrg	psav->ModeStructInit = TRUE;
2604ab47cfaaSmrg    }
2605ab47cfaaSmrg
2606ab47cfaaSmrg#if 0
2607ab47cfaaSmrg    if (xf86GetVerbosity() > 1)
2608ab47cfaaSmrg	SavagePrintRegs(pScrn);
2609ab47cfaaSmrg#endif
2610ab47cfaaSmrg
2611ab47cfaaSmrg    return;
2612ab47cfaaSmrg}
2613ab47cfaaSmrg
2614ab47cfaaSmrg
2615ab47cfaaSmrgstatic void SavageWriteMode(ScrnInfoPtr pScrn, vgaRegPtr vgaSavePtr,
2616ab47cfaaSmrg			    SavageRegPtr restore, Bool Entering)
2617ab47cfaaSmrg{
2618ab47cfaaSmrg    unsigned char tmp, cr3a, cr66;
2619ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
2620ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
2621ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
2622ab47cfaaSmrg
2623ab47cfaaSmrg
2624ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
2625ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
2626ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
2627ab47cfaaSmrg
2628ab47cfaaSmrg    TRACE(("SavageWriteMode(%x)\n", restore->mode));
2629ab47cfaaSmrg
2630ab47cfaaSmrg#ifdef XF86DRI
2631ab47cfaaSmrg    if (psav->directRenderingEnabled) {
2632ab47cfaaSmrg        DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
2633ab47cfaaSmrg        psav->LockHeld = 1;
2634ab47cfaaSmrg    }
2635ab47cfaaSmrg#endif
2636ab47cfaaSmrg
2637ab47cfaaSmrg    if (psav->IsSecondary) {
2638ab47cfaaSmrg	/* Set up the mode.  Don't clear video RAM. */
2639ab47cfaaSmrg	SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh );
2640ab47cfaaSmrg	SavageSetGBD(pScrn);
2641ab47cfaaSmrg	return;
2642ab47cfaaSmrg    }
2643ab47cfaaSmrg
2644ab47cfaaSmrg    if( Entering &&
2645ab47cfaaSmrg	(!S3_SAVAGE_MOBILE_SERIES(psav->Chipset) || (psav->ForceInit))
2646ab47cfaaSmrg    )
2647ab47cfaaSmrg	SavageInitialize2DEngine(pScrn);
2648ab47cfaaSmrg
2649ab47cfaaSmrg    /*
2650ab47cfaaSmrg     * If we figured out a VESA mode number for this timing, just use
2651ab47cfaaSmrg     * the S3 BIOS to do the switching, with a few additional tweaks.
2652ab47cfaaSmrg     */
2653ab47cfaaSmrg
2654ab47cfaaSmrg    if( psav->UseBIOS && restore->mode > 0x13 )
2655ab47cfaaSmrg    {
2656ab47cfaaSmrg	int width;
2657ab47cfaaSmrg	unsigned short cr6d;
2658ab47cfaaSmrg	unsigned short cr79 = 0;
2659ab47cfaaSmrg
2660ab47cfaaSmrg	/* Set up the mode.  Don't clear video RAM. */
2661ab47cfaaSmrg	SavageSetVESAMode( psav, restore->mode | 0x8000, restore->refresh );
2662ab47cfaaSmrg
2663ab47cfaaSmrg	/* Restore the DAC. */
2664ab47cfaaSmrg	vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_CMAP);
2665ab47cfaaSmrg
2666ab47cfaaSmrg	/* Unlock the extended registers. */
2667ab47cfaaSmrg
2668ab47cfaaSmrg#if 0
2669ab47cfaaSmrg	/* Which way is better? */
2670ab47cfaaSmrg	hwp->writeCrtc( hwp, 0x38, 0x48 );
2671ab47cfaaSmrg	hwp->writeCrtc( hwp, 0x39, 0xa0 );
2672ab47cfaaSmrg	hwp->writeSeq( hwp, 0x08, 0x06 );
2673ab47cfaaSmrg#endif
2674ab47cfaaSmrg
2675ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x4838);
2676ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0xA039);
2677ab47cfaaSmrg	VGAOUT16(0x3c4, 0x0608);
2678ab47cfaaSmrg
2679ab47cfaaSmrg	/* Enable linear addressing. */
2680ab47cfaaSmrg
2681ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x1358);
2682ab47cfaaSmrg
2683ab47cfaaSmrg	/* Disable old MMIO. */
2684ab47cfaaSmrg
2685ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x53);
2686ab47cfaaSmrg	VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & ~0x10);
2687ab47cfaaSmrg
2688ab47cfaaSmrg	/* Disable HW cursor */
2689ab47cfaaSmrg
2690ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x0045);
2691ab47cfaaSmrg
2692ab47cfaaSmrg	/* Set the color mode. */
2693ab47cfaaSmrg
2694ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x67);
2695ab47cfaaSmrg	VGAOUT8(vgaCRReg, restore->CR67);
2696ab47cfaaSmrg
2697ab47cfaaSmrg	/* Enable gamma correction, set CLUT to 8 bit */
2698ab47cfaaSmrg
2699ab47cfaaSmrg	VGAOUT8(0x3c4, 0x1b);
2700ab47cfaaSmrg	if( (pScrn->bitsPerPixel == 32) && !psav->DGAactive
2701ab47cfaaSmrg	    && ! psav->FBStart2nd )
2702ab47cfaaSmrg		VGAOUT8(0x3c5, 0x18 );
2703ab47cfaaSmrg	else
2704ab47cfaaSmrg		VGAOUT8(0x3c5, 0x10 );
2705ab47cfaaSmrg
2706ab47cfaaSmrg	/* We may need TV/panel fixups here.  See s3bios.c line 2904. */
2707ab47cfaaSmrg
2708ab47cfaaSmrg	/* Set FIFO fetch delay. */
2709ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x85);
2710ab47cfaaSmrg	VGAOUT8(vgaCRReg, (VGAIN8(vgaCRReg) & 0xf8) | 0x03);
2711ab47cfaaSmrg
2712ab47cfaaSmrg	/* Patch CR79.  These values are magical. */
2713ab47cfaaSmrg
2714ab47cfaaSmrg	if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
2715ab47cfaaSmrg	{
2716ab47cfaaSmrg	    VGAOUT8(vgaCRIndex, 0x6d);
2717ab47cfaaSmrg	    cr6d = VGAIN8(vgaCRReg);
2718ab47cfaaSmrg
2719ab47cfaaSmrg	    cr79 = 0x04;
2720ab47cfaaSmrg
2721ab47cfaaSmrg	    if( pScrn->displayWidth >= 1024 )
2722ab47cfaaSmrg	    {
2723ab47cfaaSmrg		if(psav->primStreamBpp == 32 )
2724ab47cfaaSmrg		{
2725ab47cfaaSmrg		    if( restore->refresh >= 130 )
2726ab47cfaaSmrg			cr79 = 0x03;
2727ab47cfaaSmrg		    else if( pScrn->displayWidth >= 1280 )
2728ab47cfaaSmrg			cr79 = 0x02;
2729ab47cfaaSmrg		    else if(
2730ab47cfaaSmrg			(pScrn->displayWidth == 1024) &&
2731ab47cfaaSmrg			(restore->refresh >= 75)
2732ab47cfaaSmrg		    )
2733ab47cfaaSmrg		    {
2734ab47cfaaSmrg			if( cr6d && LCD_ACTIVE )
2735ab47cfaaSmrg			    cr79 = 0x05;
2736ab47cfaaSmrg			else
2737ab47cfaaSmrg			    cr79 = 0x08;
2738ab47cfaaSmrg		    }
2739ab47cfaaSmrg		}
2740ab47cfaaSmrg		else if( psav->primStreamBpp == 16)
2741ab47cfaaSmrg		{
2742ab47cfaaSmrg
2743ab47cfaaSmrg/* The windows driver uses 0x13 for 16-bit 130Hz, but I see terrible
2744ab47cfaaSmrg * screen artifacts with that value.  Let's keep it low for now.
2745ab47cfaaSmrg *		if( restore->refresh >= 130 )
2746ab47cfaaSmrg *		    cr79 = 0x13;
2747ab47cfaaSmrg *		else
2748ab47cfaaSmrg */
2749ab47cfaaSmrg		    if( pScrn->displayWidth == 1024 )
2750ab47cfaaSmrg		    {
2751ab47cfaaSmrg			if( cr6d && LCD_ACTIVE )
2752ab47cfaaSmrg			    cr79 = 0x08;
2753ab47cfaaSmrg			else
2754ab47cfaaSmrg			    cr79 = 0x0e;
2755ab47cfaaSmrg		    }
2756ab47cfaaSmrg		}
2757ab47cfaaSmrg	    }
2758ab47cfaaSmrg	}
2759ab47cfaaSmrg
2760ab47cfaaSmrg        if( (psav->Chipset != S3_SAVAGE2000) &&
2761ab47cfaaSmrg	    !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
2762ab47cfaaSmrg	    VGAOUT16(vgaCRIndex, (cr79 << 8) | 0x79);
2763ab47cfaaSmrg
2764ab47cfaaSmrg	/* Make sure 16-bit memory access is enabled. */
2765ab47cfaaSmrg
2766ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x0c31);
2767ab47cfaaSmrg
2768ab47cfaaSmrg	/* Enable the graphics engine. */
2769ab47cfaaSmrg
2770ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x0140);
2771ab47cfaaSmrg
2772ab47cfaaSmrg	/* Handle the pitch. */
2773ab47cfaaSmrg
2774ab47cfaaSmrg        VGAOUT8(vgaCRIndex, 0x50);
2775ab47cfaaSmrg        VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1);
2776ab47cfaaSmrg
2777ab47cfaaSmrg	width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3;
2778ab47cfaaSmrg	VGAOUT16(vgaCRIndex, ((width & 0xff) << 8) | 0x13 );
2779ab47cfaaSmrg	VGAOUT16(vgaCRIndex, ((width & 0x300) << 4) | 0x51 );
2780ab47cfaaSmrg
2781ab47cfaaSmrg	/* Some non-S3 BIOSes enable block write even on non-SGRAM devices. */
2782ab47cfaaSmrg
2783ab47cfaaSmrg	switch( psav->Chipset )
2784ab47cfaaSmrg	{
2785ab47cfaaSmrg	    case S3_SAVAGE2000:
2786ab47cfaaSmrg		VGAOUT8(vgaCRIndex, 0x73);
2787ab47cfaaSmrg		VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) & 0xdf );
2788ab47cfaaSmrg		break;
2789ab47cfaaSmrg
2790ab47cfaaSmrg	    case S3_SAVAGE3D:
2791ab47cfaaSmrg	    case S3_SAVAGE4:
2792ab47cfaaSmrg		VGAOUT8(vgaCRIndex, 0x68);
2793ab47cfaaSmrg		if( !(VGAIN8(vgaCRReg) & 0x80) )
2794ab47cfaaSmrg		{
2795ab47cfaaSmrg		    /* Not SGRAM; disable block write. */
2796ab47cfaaSmrg		    VGAOUT8(vgaCRIndex, 0x88);
2797ab47cfaaSmrg		    VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0x10);
2798ab47cfaaSmrg		}
2799ab47cfaaSmrg		break;
2800ab47cfaaSmrg	}
2801ab47cfaaSmrg
2802ab47cfaaSmrg	/* set the correct clock for some BIOSes */
2803ab47cfaaSmrg	VGAOUT8(VGA_MISC_OUT_W,
2804ab47cfaaSmrg		VGAIN8(VGA_MISC_OUT_R) | 0x0C);
2805ab47cfaaSmrg	/* Some BIOSes turn on clock doubling on non-doubled modes */
2806ab47cfaaSmrg	if (pScrn->bitsPerPixel < 24) {
2807ab47cfaaSmrg	    VGAOUT8(vgaCRIndex, 0x67);
2808ab47cfaaSmrg	    if (!(VGAIN8(vgaCRReg) & 0x10)) {
2809ab47cfaaSmrg		VGAOUT8(0x3c4, 0x15);
2810ab47cfaaSmrg		VGAOUT8(0x3c5, VGAIN8(0x3C5) & ~0x10);
2811ab47cfaaSmrg		VGAOUT8(0x3c4, 0x18);
2812ab47cfaaSmrg		VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x80);
2813ab47cfaaSmrg	    }
2814ab47cfaaSmrg	}
2815ab47cfaaSmrg
2816ab47cfaaSmrg	SavageInitialize2DEngine(pScrn);
2817ab47cfaaSmrg
2818ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x0140);
2819ab47cfaaSmrg
2820ab47cfaaSmrg	SavageSetGBD(pScrn);
2821ab47cfaaSmrg
2822ab47cfaaSmrg
2823ab47cfaaSmrg#ifdef XF86DRI
2824ab47cfaaSmrg    	if (psav->directRenderingEnabled)
2825ab47cfaaSmrg    	    DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
2826ab47cfaaSmrg    	psav->LockHeld = 0;
2827ab47cfaaSmrg#endif
2828ab47cfaaSmrg
2829ab47cfaaSmrg	return;
2830ab47cfaaSmrg    }
2831ab47cfaaSmrg
2832ab47cfaaSmrg    VGAOUT8(0x3c2, 0x23);
2833ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0x4838);
2834ab47cfaaSmrg    VGAOUT16(vgaCRIndex, 0xa039);
2835ab47cfaaSmrg    VGAOUT16(0x3c4, 0x0608);
2836ab47cfaaSmrg
2837ab47cfaaSmrg    vgaHWProtect(pScrn, TRUE);
2838ab47cfaaSmrg
2839ab47cfaaSmrg    /* will we be reenabling STREAMS for the new mode? */
2840ab47cfaaSmrg    psav->STREAMSRunning = 0;
2841ab47cfaaSmrg
2842ab47cfaaSmrg    /* reset GE to make sure nothing is going on */
2843ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2844ab47cfaaSmrg    if(VGAIN8(vgaCRReg) & 0x01)
2845ab47cfaaSmrg	SavageGEReset(pScrn,0,__LINE__,__FILE__);
2846ab47cfaaSmrg
2847ab47cfaaSmrg    /*
2848ab47cfaaSmrg     * Some Savage/MX and /IX systems go nuts when trying to exit the
2849ab47cfaaSmrg     * server after WindowMaker has displayed a gradient background.  I
2850ab47cfaaSmrg     * haven't been able to find what causes it, but a non-destructive
2851ab47cfaaSmrg     * switch to mode 3 here seems to eliminate the issue.
2852ab47cfaaSmrg     */
2853ab47cfaaSmrg
2854ab47cfaaSmrg    if( ((restore->CR31 & 0x0a) == 0) && psav->pVbe ) {
2855ab47cfaaSmrg	SavageSetTextMode( psav );
2856ab47cfaaSmrg    }
2857ab47cfaaSmrg
2858ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x67);
2859ab47cfaaSmrg    (void) VGAIN8(vgaCRReg);
2860ab47cfaaSmrg    /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */
2861ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no STREAMS yet old and new */
2862ab47cfaaSmrg
2863ab47cfaaSmrg    /* restore extended regs */
2864ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
2865ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR66);
2866ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
2867ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR3A);
2868ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x31);
2869ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR31);
2870ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x32);
2871ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR32);
2872ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x58);
2873ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR58);
2874ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x53);
2875ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR53 & 0x7f);
2876ab47cfaaSmrg
2877ab47cfaaSmrg    VGAOUT16(0x3c4, 0x0608);
2878ab47cfaaSmrg
2879ab47cfaaSmrg    /* Restore DCLK registers. */
2880ab47cfaaSmrg
2881ab47cfaaSmrg    VGAOUT8(0x3c4, 0x0e);
2882ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR0E);
2883ab47cfaaSmrg    VGAOUT8(0x3c4, 0x0f);
2884ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR0F);
2885ab47cfaaSmrg    VGAOUT8(0x3c4, 0x29);
2886ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR29);
2887ab47cfaaSmrg    VGAOUT8(0x3c4, 0x15);
2888ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR15);
2889ab47cfaaSmrg
2890ab47cfaaSmrg    /* Restore flat panel expansion registers. */
2891ab47cfaaSmrg    if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
2892ab47cfaaSmrg	S3_MOBILE_TWISTER_SERIES(psav->Chipset)) {
2893ab47cfaaSmrg	int i;
2894ab47cfaaSmrg	for( i = 0; i < 8; i++ ) {
2895ab47cfaaSmrg	    VGAOUT8(0x3c4, 0x54+i);
2896ab47cfaaSmrg	    VGAOUT8(0x3c5, restore->SR54[i]);
2897ab47cfaaSmrg	}
2898ab47cfaaSmrg    }
2899ab47cfaaSmrg
2900ab47cfaaSmrg    /* restore the standard vga regs */
2901ab47cfaaSmrg    if (xf86IsPrimaryPci(psav->PciInfo))
2902ab47cfaaSmrg	vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_ALL);
2903ab47cfaaSmrg    else
2904ab47cfaaSmrg	vgaHWRestore(pScrn, vgaSavePtr, VGA_SR_MODE);
2905ab47cfaaSmrg
2906ab47cfaaSmrg    /* extended mode timing registers */
2907ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x53);
2908ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR53);
2909ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x5d);
2910ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR5D);
2911ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x5e);
2912ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR5E);
2913ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3b);
2914ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR3B);
2915ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3c);
2916ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR3C);
2917ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x43);
2918ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR43);
2919ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x65);
2920ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR65);
2921ab47cfaaSmrg
2922ab47cfaaSmrg    /* restore the desired video mode with cr67 */
2923ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x67);
2924ab47cfaaSmrg    /*VGAOUT8(vgaCRReg, restore->CR67 & ~0x0c);*/ /* no STREAMS yet */
2925ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR67 & ~0x0e); /* no streams for new and old streams engines */
2926ab47cfaaSmrg
2927ab47cfaaSmrg    /* other mode timing and extended regs */
2928ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x34);
2929ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR34);
2930ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x40);
2931ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR40);
2932ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x42);
2933ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR42);
2934ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x45);
2935ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR45);
2936ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x50);
2937ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR50);
2938ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x51);
2939ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR51);
2940ab47cfaaSmrg
2941ab47cfaaSmrg    /* memory timings */
2942ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x36);
2943ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR36);
2944ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x60);
2945ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR60);
2946ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x68);
2947ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR68);
2948ab47cfaaSmrg    VerticalRetraceWait();
2949ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x69);
2950ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR69);
2951ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x6f);
2952ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR6F);
2953ab47cfaaSmrg
2954ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x33);
2955ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR33);
2956ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x86);
2957ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR86);
2958ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x88);
2959ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR88);
2960ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x90);
2961ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR90);
2962ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x91);
2963ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR91);
2964ab47cfaaSmrg    if( psav->Chipset == S3_SAVAGE4 )
2965ab47cfaaSmrg    {
2966ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0xb0);
2967ab47cfaaSmrg	VGAOUT8(vgaCRReg, restore->CRB0);
2968ab47cfaaSmrg    }
2969ab47cfaaSmrg
2970ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x32);
2971ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR32);
2972ab47cfaaSmrg
2973ab47cfaaSmrg    /* unlock extended seq regs */
2974ab47cfaaSmrg    VGAOUT8(0x3c4, 0x08);
2975ab47cfaaSmrg    VGAOUT8(0x3c5, 0x06);
2976ab47cfaaSmrg
2977ab47cfaaSmrg    /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that
2978ab47cfaaSmrg     * we should leave the default SR10 and SR11 values there.
2979ab47cfaaSmrg     */
2980ab47cfaaSmrg    if (restore->SR10 != 255) {
2981ab47cfaaSmrg	VGAOUT8(0x3c4, 0x10);
2982ab47cfaaSmrg	VGAOUT8(0x3c5, restore->SR10);
2983ab47cfaaSmrg	VGAOUT8(0x3c4, 0x11);
2984ab47cfaaSmrg	VGAOUT8(0x3c5, restore->SR11);
2985ab47cfaaSmrg    }
2986ab47cfaaSmrg
2987ab47cfaaSmrg    /* restore extended seq regs for dclk */
2988ab47cfaaSmrg    VGAOUT8(0x3c4, 0x0e);
2989ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR0E);
2990ab47cfaaSmrg    VGAOUT8(0x3c4, 0x0f);
2991ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR0F);
2992ab47cfaaSmrg    VGAOUT8(0x3c4, 0x12);
2993ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR12);
2994ab47cfaaSmrg    VGAOUT8(0x3c4, 0x13);
2995ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR13);
2996ab47cfaaSmrg    VGAOUT8(0x3c4, 0x29);
2997ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR29);
2998ab47cfaaSmrg
2999ab47cfaaSmrg    VGAOUT8(0x3c4, 0x18);
3000ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR18);
3001ab47cfaaSmrg    VGAOUT8(0x3c4, 0x1b);
3002ab47cfaaSmrg    if( psav->DGAactive )
3003ab47cfaaSmrg	VGAOUT8(0x3c5, restore->SR1B & ~0x08 );
3004ab47cfaaSmrg    else
3005ab47cfaaSmrg	VGAOUT8(0x3c5, restore->SR1B);
3006ab47cfaaSmrg
3007ab47cfaaSmrg    /* load new m, n pll values for dclk & mclk */
3008ab47cfaaSmrg    VGAOUT8(0x3c4, 0x15);
3009ab47cfaaSmrg    tmp = VGAIN8(0x3c5) & ~0x21;
3010ab47cfaaSmrg
3011ab47cfaaSmrg    VGAOUT8(0x3c5, tmp | 0x03);
3012ab47cfaaSmrg    VGAOUT8(0x3c5, tmp | 0x23);
3013ab47cfaaSmrg    VGAOUT8(0x3c5, tmp | 0x03);
3014ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR15);
3015ab47cfaaSmrg    usleep( 100 );
3016ab47cfaaSmrg
3017ab47cfaaSmrg    VGAOUT8(0x3c4, 0x30);
3018ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR30);
3019ab47cfaaSmrg    VGAOUT8(0x3c4, 0x08);
3020ab47cfaaSmrg    VGAOUT8(0x3c5, restore->SR08);
3021ab47cfaaSmrg
3022ab47cfaaSmrg    /* now write out cr67 in full, possibly starting STREAMS */
3023ab47cfaaSmrg    VerticalRetraceWait();
3024ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x67);
3025ab47cfaaSmrg#if 0
3026ab47cfaaSmrg    VGAOUT8(vgaCRReg, 0x50);
3027ab47cfaaSmrg    usleep(10000);
3028ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x67);
3029ab47cfaaSmrg#endif
3030ab47cfaaSmrg    VGAOUT8(vgaCRReg, restore->CR67);
3031ab47cfaaSmrg
3032ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
3033ab47cfaaSmrg    cr66 = VGAIN8(vgaCRReg);
3034ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66 | 0x80);
3035ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
3036ab47cfaaSmrg    cr3a = VGAIN8(vgaCRReg);
3037ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a | 0x80);
3038ab47cfaaSmrg
3039ab47cfaaSmrg    if (Entering)
3040ab47cfaaSmrg	SavageGEReset(pScrn,0,__LINE__,__FILE__);
3041ab47cfaaSmrg
3042ab47cfaaSmrg    if( !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
3043ab47cfaaSmrg    {
3044ab47cfaaSmrg	VerticalRetraceWait();
3045ab47cfaaSmrg	OUTREG(FIFO_CONTROL_REG, restore->MMPR0);
3046ab47cfaaSmrg	OUTREG(MIU_CONTROL_REG, restore->MMPR1);
3047ab47cfaaSmrg	OUTREG(STREAMS_TIMEOUT_REG, restore->MMPR2);
3048ab47cfaaSmrg	OUTREG(MISC_TIMEOUT_REG, restore->MMPR3);
3049ab47cfaaSmrg    }
3050ab47cfaaSmrg
3051ab47cfaaSmrg    /* If we're going into graphics mode and acceleration was enabled, */
3052ab47cfaaSmrg    /* go set up the BCI buffer and the global bitmap descriptor. */
3053ab47cfaaSmrg
3054ab47cfaaSmrg#if 0
3055ab47cfaaSmrg    if( Entering && (!psav->NoAccel) )
3056ab47cfaaSmrg    {
3057ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x50);
3058ab47cfaaSmrg	VGAOUT8(vgaCRReg, VGAIN8(vgaCRReg) | 0xC1);
3059ab47cfaaSmrg	SavageInitialize2DEngine(pScrn);
3060ab47cfaaSmrg    }
3061ab47cfaaSmrg#endif
3062ab47cfaaSmrg
3063ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
3064ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr66);
3065ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x3a);
3066ab47cfaaSmrg    VGAOUT8(vgaCRReg, cr3a);
3067ab47cfaaSmrg
3068ab47cfaaSmrg    if( Entering ) {
3069ab47cfaaSmrg	SavageInitialize2DEngine(pScrn);
3070ab47cfaaSmrg
3071ab47cfaaSmrg	VGAOUT16(vgaCRIndex, 0x0140);
3072ab47cfaaSmrg
3073ab47cfaaSmrg	SavageSetGBD(pScrn);
3074ab47cfaaSmrg    }
3075ab47cfaaSmrg
3076ab47cfaaSmrg    vgaHWProtect(pScrn, FALSE);
3077ab47cfaaSmrg
3078ab47cfaaSmrg
3079ab47cfaaSmrg#ifdef XF86DRI
3080ab47cfaaSmrg    if (psav->directRenderingEnabled)
3081ab47cfaaSmrg        DRIUnlock(screenInfo.screens[pScrn->scrnIndex]);
3082ab47cfaaSmrg    psav->LockHeld = 0;
3083ab47cfaaSmrg#endif
3084ab47cfaaSmrg
3085ab47cfaaSmrg    return;
3086ab47cfaaSmrg}
3087ab47cfaaSmrg
3088ab47cfaaSmrg
3089ab47cfaaSmrgstatic Bool SavageMapMem(ScrnInfoPtr pScrn)
3090ab47cfaaSmrg{
3091ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
30928697ee19Smrg    int err;
3093ab47cfaaSmrg
3094ab47cfaaSmrg    TRACE(("SavageMapMem()\n"));
3095ab47cfaaSmrg
3096ab47cfaaSmrg    if( S3_SAVAGE3D_SERIES(psav->Chipset) ) {
30978697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
30988697ee19Smrg        psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S3
30998697ee19Smrg            + psav->PciInfo->regions[0].base_addr;
31008697ee19Smrg        psav->FbRegion.base = psav->PciInfo->regions[0].base_addr;
31018697ee19Smrg#else
31028697ee19Smrg        psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S3
31038697ee19Smrg            + psav->PciInfo->memBase[0];
31048697ee19Smrg        psav->FbRegion.base = psav->PciInfo->memBase[0];
31058697ee19Smrg#endif
3106ab47cfaaSmrg    } else {
31078697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
31088697ee19Smrg        psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S4
31098697ee19Smrg            + psav->PciInfo->regions[0].base_addr;
31108697ee19Smrg        psav->FbRegion.base = psav->PciInfo->regions[1].base_addr;
31118697ee19Smrg#else
31128697ee19Smrg        psav->MmioRegion.base = SAVAGE_NEWMMIO_REGBASE_S4
31138697ee19Smrg            + psav->PciInfo->memBase[0];
31148697ee19Smrg        psav->FbRegion.base = psav->PciInfo->memBase[1];
31158697ee19Smrg#endif
3116ab47cfaaSmrg    }
3117ab47cfaaSmrg
31188697ee19Smrg    psav->MmioRegion.size = SAVAGE_NEWMMIO_REGSIZE;
31198697ee19Smrg    psav->FbRegion.size = psav->videoRambytes;
31208697ee19Smrg
3121ab47cfaaSmrg    /* On Paramount and Savage 2000, aperture 0 is PCI base 2.  On other
3122ab47cfaaSmrg     * chipsets it's in the same BAR as the framebuffer.
3123ab47cfaaSmrg     */
3124ab47cfaaSmrg
31258697ee19Smrg    psav->ApertureRegion.size = (psav->IsPrimary || psav->IsSecondary)
31268697ee19Smrg        ? (0x01000000 * 2) : (0x01000000 * 5);
31278697ee19Smrg
31288697ee19Smrg    if ((psav->Chipset == S3_SUPERSAVAGE)
31298697ee19Smrg        || (psav->Chipset == S3_SAVAGE2000)) {
31308697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
31318697ee19Smrg        psav->ApertureRegion.base = psav->PciInfo->regions[2].base_addr;
31328697ee19Smrg        if (psav->ApertureRegion.size > psav->PciInfo->regions[2].size)
31338697ee19Smrg            psav->ApertureRegion.size = psav->PciInfo->regions[2].size;
31348697ee19Smrg#else
31358697ee19Smrg        psav->ApertureRegion.base = psav->PciInfo->memBase[2];
31368697ee19Smrg#endif
3137ab47cfaaSmrg    } else {
31388697ee19Smrg        psav->ApertureRegion.base = psav->FbRegion.base + 0x02000000;
3139ab47cfaaSmrg    }
3140ab47cfaaSmrg
3141ab47cfaaSmrg
3142ab47cfaaSmrg
31438697ee19Smrg    if (psav->FbRegion.size != 0) {
31448697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
31458697ee19Smrg        err = pci_device_map_range(psav->PciInfo, psav->FbRegion.base,
31468697ee19Smrg                                   psav->FbRegion.size,
31478697ee19Smrg                                   (PCI_DEV_MAP_FLAG_WRITABLE
31488697ee19Smrg                                    | PCI_DEV_MAP_FLAG_WRITE_COMBINE),
31498697ee19Smrg                                   & psav->FbRegion.memory);
31508697ee19Smrg#else
31518697ee19Smrg        psav->FbRegion.memory =
31528697ee19Smrg            xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
31538697ee19Smrg                          psav->PciTag, psav->FbRegion.base,
31548697ee19Smrg                          psav->FbRegion.size);
31558697ee19Smrg        err = (psav->FbRegion.memory == NULL) ? errno : 0;
31568697ee19Smrg#endif
31578697ee19Smrg        if (err) {
31588697ee19Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
31598697ee19Smrg                       "Internal error: could not map framebuffer range (%d, %s).\n",
31608697ee19Smrg                       err, strerror(err));
31618697ee19Smrg            return FALSE;
31628697ee19Smrg        }
3163ab47cfaaSmrg
31648697ee19Smrg        psav->FBBase = psav->FbRegion.memory;
31658697ee19Smrg        psav->FBStart = (psav->IsSecondary)
31668697ee19Smrg            ? psav->FBBase + 0x1000000 : psav->FBBase;
3167ab47cfaaSmrg    }
3168ab47cfaaSmrg
31698697ee19Smrg    if (psav->ApertureRegion.memory == NULL) {
31708697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
31718697ee19Smrg        err = pci_device_map_range(psav->PciInfo, psav->ApertureRegion.base,
31728697ee19Smrg                                   psav->ApertureRegion.size,
31738697ee19Smrg                                   (PCI_DEV_MAP_FLAG_WRITABLE
31748697ee19Smrg                                    | PCI_DEV_MAP_FLAG_WRITE_COMBINE),
31758697ee19Smrg                                   & psav->ApertureRegion.memory);
31768697ee19Smrg#else
31778697ee19Smrg        psav->ApertureRegion.memory =
31788697ee19Smrg            xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
31798697ee19Smrg                          psav->PciTag, psav->ApertureRegion.base,
31808697ee19Smrg                          psav->ApertureRegion.size);
31818697ee19Smrg        err = (psav->ApertureRegion.memory == NULL) ? errno : 0;
31828697ee19Smrg#endif
31838697ee19Smrg        if (err) {
31848697ee19Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
31858697ee19Smrg                       "Internal error: could not map aperture range (%d, %s).\n",
31868697ee19Smrg                       err, strerror(err));
31878697ee19Smrg            return FALSE;
31888697ee19Smrg        }
3189ab47cfaaSmrg
31908697ee19Smrg        psav->ApertureMap = (psav->IsSecondary)
31918697ee19Smrg            ? psav->ApertureRegion.memory + 0x1000000
31928697ee19Smrg            : psav->ApertureRegion.memory;
31938697ee19Smrg    }
3194ab47cfaaSmrg
31958697ee19Smrg    if (psav->MmioRegion.memory == NULL) {
31968697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
31978697ee19Smrg        err = pci_device_map_range(psav->PciInfo, psav->MmioRegion.base,
31988697ee19Smrg                                   psav->MmioRegion.size,
31998697ee19Smrg                                   (PCI_DEV_MAP_FLAG_WRITABLE),
32008697ee19Smrg                                   & psav->MmioRegion.memory);
32018697ee19Smrg#else
32028697ee19Smrg        psav->MmioRegion.memory =
32038697ee19Smrg            xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
32048697ee19Smrg                          psav->PciTag, psav->MmioRegion.base,
32058697ee19Smrg                          psav->MmioRegion.size);
32068697ee19Smrg        err = (psav->MmioRegion.memory == NULL) ? errno : 0;
32078697ee19Smrg#endif
32088697ee19Smrg        if (err) {
32098697ee19Smrg            xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
32108697ee19Smrg                       "Internal error: could not map MMIO range (%d, %s).\n",
32118697ee19Smrg                       err, strerror(err));
32128697ee19Smrg            return FALSE;
32138697ee19Smrg        }
3214ab47cfaaSmrg
32158697ee19Smrg        psav->MapBase = psav->MmioRegion.memory;
32168697ee19Smrg        psav->BciMem = psav->MapBase + 0x10000;
3217ab47cfaaSmrg
32188697ee19Smrg        SavageEnableMMIO(pScrn);
3219ab47cfaaSmrg    }
3220ab47cfaaSmrg
32218697ee19Smrg    pScrn->memPhysBase = psav->FbRegion.base;
3222ab47cfaaSmrg    return TRUE;
3223ab47cfaaSmrg}
3224ab47cfaaSmrg
3225ab47cfaaSmrg
3226ab47cfaaSmrgstatic void SavageUnmapMem(ScrnInfoPtr pScrn, int All)
3227ab47cfaaSmrg{
3228ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
3229ab47cfaaSmrg
3230ab47cfaaSmrg    TRACE(("SavageUnmapMem(%x,%x)\n", psav->MapBase, psav->FBBase));
3231ab47cfaaSmrg
3232ab47cfaaSmrg    if (psav->PrimaryVidMapped) {
32338697ee19Smrg        vgaHWUnmapMem(pScrn);
32348697ee19Smrg        psav->PrimaryVidMapped = FALSE;
3235ab47cfaaSmrg    }
3236ab47cfaaSmrg
3237ab47cfaaSmrg    SavageDisableMMIO(pScrn);
3238ab47cfaaSmrg
32398697ee19Smrg    if (All && (psav->MmioRegion.memory != NULL)) {
32408697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
32418697ee19Smrg        pci_device_unmap_range(psav->PciInfo,
32428697ee19Smrg                               psav->MmioRegion.memory,
32438697ee19Smrg                               psav->MmioRegion.size);
32448697ee19Smrg#else
32458697ee19Smrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer)psav->MapBase,
32468697ee19Smrg                        SAVAGE_NEWMMIO_REGSIZE);
32478697ee19Smrg#endif
32488697ee19Smrg
32498697ee19Smrg        psav->MmioRegion.memory = NULL;
32508697ee19Smrg        psav->MapBase = 0;
32518697ee19Smrg        psav->BciMem = 0;
32528697ee19Smrg    }
32538697ee19Smrg
32548697ee19Smrg    if (psav->FbRegion.memory != NULL) {
32558697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
32568697ee19Smrg        pci_device_unmap_range(psav->PciInfo,
32578697ee19Smrg                               psav->FbRegion.memory,
32588697ee19Smrg                               psav->FbRegion.size);
32598697ee19Smrg#else
32608697ee19Smrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer)psav->FbRegion.base,
32618697ee19Smrg                        psav->FbRegion.size);
32628697ee19Smrg#endif
3263ab47cfaaSmrg    }
3264ab47cfaaSmrg
32658697ee19Smrg    if (psav->ApertureRegion.memory != NULL) {
32668697ee19Smrg#ifdef XSERVER_LIBPCIACCESS
32678697ee19Smrg        pci_device_unmap_range(psav->PciInfo,
32688697ee19Smrg                               psav->ApertureRegion.memory,
32698697ee19Smrg                               psav->ApertureRegion.size);
32708697ee19Smrg#else
32718697ee19Smrg        xf86UnMapVidMem(pScrn->scrnIndex, (pointer)psav->ApertureRegion.base,
32728697ee19Smrg                        psav->ApertureRegion.size);
32738697ee19Smrg#endif
3274ab47cfaaSmrg    }
32758697ee19Smrg
32768697ee19Smrg    psav->FbRegion.memory = NULL;
32778697ee19Smrg    psav->ApertureRegion.memory = NULL;
3278ab47cfaaSmrg    psav->FBBase = 0;
3279ab47cfaaSmrg    psav->FBStart = 0;
3280ab47cfaaSmrg    psav->ApertureMap = 0;
3281ab47cfaaSmrg
3282ab47cfaaSmrg    return;
3283ab47cfaaSmrg}
3284ab47cfaaSmrg
3285ab47cfaaSmrg#ifdef XF86DRI
3286ab47cfaaSmrgstatic Bool SavageCheckAvailableRamFor3D(ScrnInfoPtr pScrn)
3287ab47cfaaSmrg{
3288ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
3289ab47cfaaSmrg    int cpp = pScrn->bitsPerPixel / 8;
3290ab47cfaaSmrg    int tiledBufferSize, RamNeededFor3D;
3291ab47cfaaSmrg
3292ab47cfaaSmrg    if (cpp == 2) {
3293ab47cfaaSmrg        tiledBufferSize = ((pScrn->virtualX+63)/64)*((pScrn->virtualY+15)/16) * 2048;
3294ab47cfaaSmrg    } else {
3295ab47cfaaSmrg        tiledBufferSize = ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16) * 2048;
3296ab47cfaaSmrg    }
3297ab47cfaaSmrg
3298ab47cfaaSmrg    RamNeededFor3D = 4096 + /* hw cursor*/
3299ab47cfaaSmrg                     psav->cobSize + /*COB*/
3300ab47cfaaSmrg                     tiledBufferSize + /* front buffer */
3301ab47cfaaSmrg                     tiledBufferSize + /* back buffer */
3302ab47cfaaSmrg                     tiledBufferSize; /* depth buffer */
3303ab47cfaaSmrg
3304ab47cfaaSmrg    xf86DrvMsg(pScrn->scrnIndex,X_INFO,
3305ab47cfaaSmrg		"%d kB of Videoram needed for 3D; %d kB of Videoram available\n",
3306ab47cfaaSmrg		RamNeededFor3D/1024, psav->videoRambytes/1024);
3307ab47cfaaSmrg
3308ab47cfaaSmrg    if (RamNeededFor3D <= psav->videoRambytes) {
3309ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Sufficient Videoram available for 3D\n");
3310ab47cfaaSmrg	return TRUE;
3311ab47cfaaSmrg    } else {
3312ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"Insufficient Videoram available for 3D -- "
3313ab47cfaaSmrg					"Try a lower color depth or smaller desktop.  "
3314ab47cfaaSmrg			"For integrated savages try increasing the videoram in the BIOS.\n");
3315ab47cfaaSmrg	return FALSE;
3316ab47cfaaSmrg    }
3317ab47cfaaSmrg}
3318ab47cfaaSmrg#endif
3319ab47cfaaSmrg
3320ab47cfaaSmrgstatic void SavageInitStatus(ScrnInfoPtr pScrn)
3321ab47cfaaSmrg{
3322ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
3323ab47cfaaSmrg
3324ab47cfaaSmrg    switch( psav->Chipset ) {
3325ab47cfaaSmrg	case S3_SAVAGE3D:
3326ab47cfaaSmrg	case S3_SAVAGE_MX:
3327ab47cfaaSmrg	    psav->WaitQueue	= WaitQueue3D;
3328ab47cfaaSmrg	    psav->WaitIdle	= WaitIdle3D;
3329ab47cfaaSmrg	    psav->WaitIdleEmpty	= WaitIdleEmpty3D;
3330ab47cfaaSmrg	    psav->bciUsedMask   = 0x1ffff;
3331ab47cfaaSmrg	    psav->eventStatusReg= 1;
3332ab47cfaaSmrg	    break;
3333ab47cfaaSmrg
3334ab47cfaaSmrg	case S3_SAVAGE4:
3335ab47cfaaSmrg	case S3_PROSAVAGE:
3336ab47cfaaSmrg	case S3_SUPERSAVAGE:
3337ab47cfaaSmrg	case S3_PROSAVAGEDDR:
3338ab47cfaaSmrg	case S3_TWISTER:
3339ab47cfaaSmrg	    psav->WaitQueue	= WaitQueue4;
3340ab47cfaaSmrg	    psav->WaitIdle	= WaitIdle4;
3341ab47cfaaSmrg	    psav->WaitIdleEmpty	= WaitIdleEmpty4;
3342ab47cfaaSmrg	    psav->bciUsedMask   = 0x1fffff;
3343ab47cfaaSmrg	    psav->eventStatusReg= 1;
3344ab47cfaaSmrg	    break;
3345ab47cfaaSmrg
3346ab47cfaaSmrg	case S3_SAVAGE2000:
3347ab47cfaaSmrg	    psav->WaitQueue	= WaitQueue2K;
3348ab47cfaaSmrg	    psav->WaitIdle	= WaitIdle2K;
3349ab47cfaaSmrg	    psav->WaitIdleEmpty	= WaitIdleEmpty2K;
3350ab47cfaaSmrg	    psav->bciUsedMask   = 0xfffff;
3351ab47cfaaSmrg	    psav->eventStatusReg= 2;
3352ab47cfaaSmrg	    break;
3353ab47cfaaSmrg    }
3354ab47cfaaSmrg}
3355ab47cfaaSmrg
3356ab47cfaaSmrgstatic void SavageInitShadowStatus(ScrnInfoPtr pScrn)
3357ab47cfaaSmrg{
3358ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
3359ab47cfaaSmrg
3360ab47cfaaSmrg    psav->ShadowStatus = psav->ConfigShadowStatus;
3361ab47cfaaSmrg
3362ab47cfaaSmrg    SavageInitStatus(pScrn);
3363ab47cfaaSmrg
3364ab47cfaaSmrg    if( psav->ShadowStatus ) {
3365ab47cfaaSmrg	psav->ShadowPhysical =
33668697ee19Smrg	    psav->FbRegion.base + psav->CursorKByte*1024 + 4096 - 32;
3367ab47cfaaSmrg
3368ab47cfaaSmrg	psav->ShadowVirtual = (CARD32 *)
3369ab47cfaaSmrg	    (psav->FBBase + psav->CursorKByte*1024 + 4096 - 32);
3370ab47cfaaSmrg
3371ab47cfaaSmrg	xf86DrvMsg( pScrn->scrnIndex, X_PROBED,
3372ab47cfaaSmrg		    "Shadow area physical %08lx, linear %p\n",
3373ab47cfaaSmrg		    psav->ShadowPhysical, (void *)psav->ShadowVirtual );
3374ab47cfaaSmrg
3375ab47cfaaSmrg	psav->WaitQueue = ShadowWaitQueue;
3376ab47cfaaSmrg	psav->WaitIdle = ShadowWait;
3377ab47cfaaSmrg	psav->WaitIdleEmpty = ShadowWait;
3378ab47cfaaSmrg    }
3379ab47cfaaSmrg
3380ab47cfaaSmrg    if( psav->Chipset == S3_SAVAGE2000 )
3381ab47cfaaSmrg	psav->dwBCIWait2DIdle = 0xc0040000;
3382ab47cfaaSmrg    else
3383ab47cfaaSmrg	psav->dwBCIWait2DIdle = 0xc0020000;
3384ab47cfaaSmrg}
3385ab47cfaaSmrg
3386ab47cfaaSmrgstatic Bool SavageScreenInit(int scrnIndex, ScreenPtr pScreen,
3387ab47cfaaSmrg			     int argc, char **argv)
3388ab47cfaaSmrg{
3389ab47cfaaSmrg    ScrnInfoPtr pScrn;
3390ab47cfaaSmrg    SavagePtr psav;
3391ab47cfaaSmrg    EntityInfoPtr pEnt;
3392ab47cfaaSmrg    int ret;
3393ab47cfaaSmrg    int colormapFlags;
3394ab47cfaaSmrg
3395ab47cfaaSmrg    TRACE(("SavageScreenInit()\n"));
3396ab47cfaaSmrg
3397ab47cfaaSmrg    pScrn = xf86Screens[pScreen->myNum];
3398ab47cfaaSmrg    psav = SAVPTR(pScrn);
3399ab47cfaaSmrg
3400ab47cfaaSmrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
3401ab47cfaaSmrg    if (!psav->pVbe)
3402ab47cfaaSmrg	psav->pVbe = VBEInit(NULL, pEnt->index);
3403ab47cfaaSmrg
3404ab47cfaaSmrg    SavageEnableMMIO(pScrn);
3405ab47cfaaSmrg
3406ab47cfaaSmrg    if (!SavageMapMem(pScrn))
3407ab47cfaaSmrg	return FALSE;
3408ab47cfaaSmrg
3409ab47cfaaSmrg    psav->FBStart2nd = 0;
3410ab47cfaaSmrg
3411ab47cfaaSmrg    if (psav->overlayDepth) {
3412ab47cfaaSmrg	if ((pScrn->virtualX * pScrn->virtualY *
3413ab47cfaaSmrg	     (DEPTH_BPP(DEPTH_2ND(pScrn))) >> 3)
3414ab47cfaaSmrg	     > (psav->CursorKByte * 1024))
3415ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex,X_WARNING,
3416ab47cfaaSmrg		       "Not enough memory for overlay mode: disabling\n");
3417ab47cfaaSmrg	else psav->FBStart2nd  = psav->FBStart
3418ab47cfaaSmrg		 + ((pScrn->virtualX * pScrn->virtualY + 0xff) & ~0xff);
3419ab47cfaaSmrg
3420ab47cfaaSmrg    }
3421ab47cfaaSmrg
3422ab47cfaaSmrg    SavageInitShadowStatus(pScrn);
3423ab47cfaaSmrg    psav->ShadowCounter = 0;
3424ab47cfaaSmrg
3425ab47cfaaSmrg    SavageSave(pScrn);
3426ab47cfaaSmrg
3427ab47cfaaSmrg    vgaHWBlankScreen(pScrn, TRUE);
3428ab47cfaaSmrg
3429ab47cfaaSmrg#ifdef XF86DRI
3430ab47cfaaSmrg    if (!xf86ReturnOptValBool(psav->Options, OPTION_DRI, TRUE)) {
3431ab47cfaaSmrg	psav->directRenderingEnabled = FALSE;
3432ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
3433ab47cfaaSmrg		   "Direct rendering forced off\n");
3434ab47cfaaSmrg    } else if (psav->IsSecondary) {
3435ab47cfaaSmrg	psav->directRenderingEnabled = FALSE;
3436ab47cfaaSmrg    } else if (xf86IsEntityShared(psav->pEnt->index)) {
3437ab47cfaaSmrg	    /* Xinerama has sync problem with DRI, disable it for now */
3438ab47cfaaSmrg	    psav->directRenderingEnabled = FALSE;
3439ab47cfaaSmrg	    xf86DrvMsg(scrnIndex, X_WARNING,
3440ab47cfaaSmrg			"Direct Rendering Disabled -- "
3441ab47cfaaSmrg			"Dual-head configuration is not working with "
3442ab47cfaaSmrg			"DRI at present.\n");
3443ab47cfaaSmrg    } else if (/*!psav->bTiled*/psav->bDisableTile) {
3444ab47cfaaSmrg            xf86DrvMsg(scrnIndex, X_WARNING,
3445ab47cfaaSmrg	    		"Direct Rendering requires a tiled framebuffer -- "
3446ab47cfaaSmrg			"Set Option \"DisableTile\" \"false\"\n");
3447ab47cfaaSmrg    } else if (psav->cobSize == 0) {
3448ab47cfaaSmrg            xf86DrvMsg(scrnIndex, X_WARNING,
3449ab47cfaaSmrg	    		"Direct Rendering requires the COB -- "
3450ab47cfaaSmrg			"Set Option \"DisableCOB\" \"false\"\n");
3451ab47cfaaSmrg    } else if (((psav->Chipset == S3_TWISTER)
3452ab47cfaaSmrg        || (psav->Chipset == S3_PROSAVAGE)
3453ab47cfaaSmrg        || (psav->Chipset == S3_SAVAGE4)
3454ab47cfaaSmrg        || (psav->Chipset == S3_SAVAGE_MX)
3455ab47cfaaSmrg	|| (psav->Chipset == S3_SAVAGE3D)
3456ab47cfaaSmrg	|| (psav->Chipset == S3_SUPERSAVAGE)
3457ab47cfaaSmrg        || (psav->Chipset == S3_PROSAVAGEDDR))
3458ab47cfaaSmrg	&& (!psav->NoAccel)
3459ab47cfaaSmrg	&& (SavageCheckAvailableRamFor3D(pScrn))) {
3460ab47cfaaSmrg        /* Setup DRI after visuals have been established */
3461ab47cfaaSmrg        psav->directRenderingEnabled = SAVAGEDRIScreenInit(pScreen);
3462ab47cfaaSmrg	/* If DRI init failed, reset shadow status. */
3463ab47cfaaSmrg	if (!psav->directRenderingEnabled &&
3464ab47cfaaSmrg	    psav->ShadowStatus != psav->ConfigShadowStatus) {
3465ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n");
3466ab47cfaaSmrg	    SavageInitShadowStatus(pScrn);
3467ab47cfaaSmrg	}
3468ab47cfaaSmrg	/* If shadow status was enabled for DRI, hook up the shadow
3469ab47cfaaSmrg	 * waiting functions now. */
3470ab47cfaaSmrg	else if (psav->ShadowStatus && !psav->ConfigShadowStatus) {
3471ab47cfaaSmrg	    psav->WaitQueue = ShadowWaitQueue;
3472ab47cfaaSmrg	    psav->WaitIdle = ShadowWait;
3473ab47cfaaSmrg	    psav->WaitIdleEmpty = ShadowWait;
3474ab47cfaaSmrg	}
3475ab47cfaaSmrg    } else
3476ab47cfaaSmrg        psav->directRenderingEnabled = FALSE;
3477ab47cfaaSmrg
3478ab47cfaaSmrg    if(psav->directRenderingEnabled) {
3479ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"DRI is enabled\n");
3480ab47cfaaSmrg    }
3481ab47cfaaSmrg    else {
3482ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex,X_ERROR,"DRI isn't enabled\n");
3483ab47cfaaSmrg    }
3484ab47cfaaSmrg#endif
3485ab47cfaaSmrg
3486ab47cfaaSmrg    if (!SavageModeInit(pScrn, pScrn->currentMode))
3487ab47cfaaSmrg	return FALSE;
3488ab47cfaaSmrg
3489ab47cfaaSmrg    miClearVisualTypes();
3490ab47cfaaSmrg
3491ab47cfaaSmrg    {
3492ab47cfaaSmrg 	int visual;
3493ab47cfaaSmrg
3494ab47cfaaSmrg 	visual = ((psav->FBStart2nd && pScrn->bitsPerPixel > 8)
3495ab47cfaaSmrg		   || pScrn->bitsPerPixel == 16) ? TrueColorMask
3496ab47cfaaSmrg	    : miGetDefaultVisualMask(DEPTH_BPP(pScrn->depth));
3497ab47cfaaSmrg 	if (!miSetVisualTypes(pScrn->depth, visual,
3498ab47cfaaSmrg  			      pScrn->rgbBits, pScrn->defaultVisual))
3499ab47cfaaSmrg  	    return FALSE;
3500ab47cfaaSmrg
3501ab47cfaaSmrg 	if (psav->FBStart2nd) {/* we have overlay */
3502ab47cfaaSmrg 	    visual = psav->overlayDepth > 8 ? TrueColorMask :
3503ab47cfaaSmrg 		miGetDefaultVisualMask(DEPTH_BPP(psav->overlayDepth));
3504ab47cfaaSmrg 	    if (!miSetVisualTypes(psav->overlayDepth, visual,
3505ab47cfaaSmrg 				  psav->overlayDepth > 8 ? 8 : 6,
3506ab47cfaaSmrg 				  pScrn->defaultVisual))
3507ab47cfaaSmrg 		return FALSE;
3508ab47cfaaSmrg 	}
3509ab47cfaaSmrg     }
3510ab47cfaaSmrg     if (!miSetPixmapDepths ())
3511ab47cfaaSmrg	 return FALSE;
3512ab47cfaaSmrg
3513ab47cfaaSmrg    ret = SavageInternalScreenInit(scrnIndex, pScreen);
3514ab47cfaaSmrg    if (!ret)
3515ab47cfaaSmrg	return FALSE;
3516ab47cfaaSmrg
3517ab47cfaaSmrg    xf86SetBlackWhitePixels(pScreen);
3518ab47cfaaSmrg
3519ab47cfaaSmrg    {
3520ab47cfaaSmrg	VisualPtr visual;
3521ab47cfaaSmrg	visual = pScreen->visuals + pScreen->numVisuals;
3522ab47cfaaSmrg	while (--visual >= pScreen->visuals) {
3523ab47cfaaSmrg	    if ((visual->class | DynamicClass) == DirectColor
3524ab47cfaaSmrg		&& visual->nplanes > MAX_PSEUDO_DEPTH) {
3525ab47cfaaSmrg		if (visual->nplanes == pScrn->depth) {
3526ab47cfaaSmrg		    visual->offsetRed = pScrn->offset.red;
3527ab47cfaaSmrg		    visual->offsetGreen = pScrn->offset.green;
3528ab47cfaaSmrg		    visual->offsetBlue = pScrn->offset.blue;
3529ab47cfaaSmrg		    visual->redMask = pScrn->mask.red;
3530ab47cfaaSmrg		    visual->greenMask = pScrn->mask.green;
3531ab47cfaaSmrg		    visual->blueMask = pScrn->mask.blue;
3532ab47cfaaSmrg		} else if (visual->offsetRed > 8
3533ab47cfaaSmrg			   || visual->offsetGreen > 8
3534ab47cfaaSmrg			   || visual->offsetBlue > 8) {
3535ab47cfaaSmrg	/*
3536ab47cfaaSmrg	 * mi has set these wrong. fix it here -- we cannot use pScrn
3537ab47cfaaSmrg	 * as this is set up for the default depth 8.
3538ab47cfaaSmrg	 */
3539ab47cfaaSmrg		    int tmp;
3540ab47cfaaSmrg		    int c_s = 0;
3541ab47cfaaSmrg
3542ab47cfaaSmrg		    tmp = visual->offsetBlue;
3543ab47cfaaSmrg		    visual->offsetBlue = visual->offsetRed;
3544ab47cfaaSmrg		    visual->offsetRed = tmp;
3545ab47cfaaSmrg		    tmp = visual->blueMask;
3546ab47cfaaSmrg		    visual->blueMask = visual->redMask;
3547ab47cfaaSmrg		    visual->redMask = tmp;
3548ab47cfaaSmrg		    switch (DEPTH_2ND(pScrn)) {
3549ab47cfaaSmrg			case 16:
3550ab47cfaaSmrg			    visual->offsetRed = 11;
3551ab47cfaaSmrg			    visual->offsetGreen = 5;
3552ab47cfaaSmrg			    visual->offsetBlue = 0;
3553ab47cfaaSmrg			    visual->redMask = 0xF800;
3554ab47cfaaSmrg			    visual->greenMask = 0x7E0;
3555ab47cfaaSmrg			    visual->blueMask = 0x1F;
3556ab47cfaaSmrg			    break;
3557ab47cfaaSmrg			case 24:
3558ab47cfaaSmrg			    visual->offsetRed = 16;
3559ab47cfaaSmrg			    visual->offsetGreen = 8;
3560ab47cfaaSmrg			    visual->offsetBlue = 0;
3561ab47cfaaSmrg			    visual->redMask = 0xFF0000;
3562ab47cfaaSmrg			    visual->greenMask = 0xFF00;
3563ab47cfaaSmrg			    visual->blueMask = 0xFF;
3564ab47cfaaSmrg			    c_s = 2;
3565ab47cfaaSmrg			    break;
3566ab47cfaaSmrg		    }
3567ab47cfaaSmrg		    psav->overlay.redMask = visual->redMask;
3568ab47cfaaSmrg		    psav->overlay.greenMask = visual->greenMask;
3569ab47cfaaSmrg		    psav->overlay.blueMask = visual->blueMask;
3570ab47cfaaSmrg		    psav->overlay.redShift = visual->offsetRed + c_s;
3571ab47cfaaSmrg		    psav->overlay.greenShift = visual->offsetGreen + c_s;
3572ab47cfaaSmrg		    psav->overlay.blueShift = visual->offsetBlue + c_s;
3573ab47cfaaSmrg		}
3574ab47cfaaSmrg	    }
3575ab47cfaaSmrg	}
3576ab47cfaaSmrg    }
3577ab47cfaaSmrg
3578ab47cfaaSmrg    /* must be after RGB ordering fixed */
3579ab47cfaaSmrg    fbPictureInit (pScreen, 0, 0);
3580ab47cfaaSmrg
3581ab47cfaaSmrg    if( !psav->NoAccel ) {
3582ab47cfaaSmrg	SavageInitAccel(pScreen);
3583ab47cfaaSmrg    }
3584ab47cfaaSmrg
3585ab47cfaaSmrg    miInitializeBackingStore(pScreen);
3586ab47cfaaSmrg    xf86SetBackingStore(pScreen);
3587ab47cfaaSmrg
3588ab47cfaaSmrg    if( !psav->shadowFB && !psav->useEXA )
3589ab47cfaaSmrg	SavageDGAInit(pScreen);
3590ab47cfaaSmrg
3591ab47cfaaSmrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
3592ab47cfaaSmrg
3593ab47cfaaSmrg    if (psav->hwcursor)
3594ab47cfaaSmrg	if (!SavageHWCursorInit(pScreen))
3595ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
3596ab47cfaaSmrg	       "Hardware cursor initialization failed\n");
3597ab47cfaaSmrg
3598ab47cfaaSmrg    if (psav->shadowFB) {
3599ab47cfaaSmrg	RefreshAreaFuncPtr refreshArea = SavageRefreshArea;
3600ab47cfaaSmrg
3601ab47cfaaSmrg	if(psav->rotate) {
3602ab47cfaaSmrg	    if (!psav->PointerMoved) {
3603ab47cfaaSmrg		psav->PointerMoved = pScrn->PointerMoved;
3604ab47cfaaSmrg		pScrn->PointerMoved = SavagePointerMoved;
3605ab47cfaaSmrg	    }
3606ab47cfaaSmrg
3607ab47cfaaSmrg	    switch(pScrn->bitsPerPixel) {
3608ab47cfaaSmrg	    case 8:	refreshArea = SavageRefreshArea8;	break;
3609ab47cfaaSmrg	    case 16:	refreshArea = SavageRefreshArea16;	break;
3610ab47cfaaSmrg	    case 24:	refreshArea = SavageRefreshArea24;	break;
3611ab47cfaaSmrg	    case 32:	refreshArea = SavageRefreshArea32;	break;
3612ab47cfaaSmrg	    }
3613ab47cfaaSmrg	}
3614ab47cfaaSmrg
3615ab47cfaaSmrg	ShadowFBInit(pScreen, refreshArea);
3616ab47cfaaSmrg    }
3617ab47cfaaSmrg
3618ab47cfaaSmrg    if (!miCreateDefColormap(pScreen))
3619ab47cfaaSmrg	    return FALSE;
3620ab47cfaaSmrg
3621ab47cfaaSmrg    colormapFlags =  CMAP_RELOAD_ON_MODE_SWITCH
3622ab47cfaaSmrg	| ((psav->FBStart2nd) ? 0 : CMAP_PALETTED_TRUECOLOR);
3623ab47cfaaSmrg
3624ab47cfaaSmrg    if (psav->Chipset == S3_SAVAGE4) {
3625ab47cfaaSmrg        if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPaletteSavage4,
3626ab47cfaaSmrg				 NULL, colormapFlags ))
3627ab47cfaaSmrg	    return FALSE;
3628ab47cfaaSmrg    } else {
3629ab47cfaaSmrg        if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits, SavageLoadPalette, NULL,
3630ab47cfaaSmrg				 colormapFlags ))
3631ab47cfaaSmrg 	    return FALSE;
3632ab47cfaaSmrg    }
3633ab47cfaaSmrg
3634ab47cfaaSmrg    vgaHWBlankScreen(pScrn, FALSE);
3635ab47cfaaSmrg
3636ab47cfaaSmrg    psav->CloseScreen = pScreen->CloseScreen;
3637ab47cfaaSmrg    pScreen->SaveScreen = SavageSaveScreen;
3638ab47cfaaSmrg    pScreen->CloseScreen = SavageCloseScreen;
3639ab47cfaaSmrg
3640ab47cfaaSmrg    if (xf86DPMSInit(pScreen, SavageDPMS, 0) == FALSE)
3641ab47cfaaSmrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed\n");
3642ab47cfaaSmrg
3643ab47cfaaSmrg#ifdef XF86DRI
3644ab47cfaaSmrg    if (psav->directRenderingEnabled) {
3645ab47cfaaSmrg        /* complete the DRI setup.*/
3646ab47cfaaSmrg        psav->directRenderingEnabled = SAVAGEDRIFinishScreenInit(pScreen);
3647ab47cfaaSmrg	/* If DRI initialization failed, reset shadow status and
3648ab47cfaaSmrg	 * reinitialize 2D engine. */
3649ab47cfaaSmrg	if (!psav->directRenderingEnabled &&
3650ab47cfaaSmrg	    psav->ShadowStatus != psav->ConfigShadowStatus) {
3651ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Resetting ShadowStatus.\n");
3652ab47cfaaSmrg	    SavageInitShadowStatus(pScrn);
3653ab47cfaaSmrg	    SavageInitialize2DEngine(pScrn);
3654ab47cfaaSmrg	}
3655ab47cfaaSmrg    }
3656ab47cfaaSmrg    if (psav->directRenderingEnabled) {
3657ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Direct rendering enabled\n");
3658ab47cfaaSmrg    } else {
3659ab47cfaaSmrg        xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Direct rendering disabled\n");
3660ab47cfaaSmrg    }
3661ab47cfaaSmrg#endif
3662ab47cfaaSmrg
36638697ee19Smrg    SavagePanningCheck(pScrn, pScrn->currentMode);
3664ab47cfaaSmrg#ifdef XvExtension
3665ab47cfaaSmrg    if( !psav->FBStart2nd && !psav->NoAccel  /*&& !SavagePanningCheck(pScrn)*/ ) {
3666ab47cfaaSmrg	if (psav->IsSecondary)
3667ab47cfaaSmrg            /* Xv should work on crtc2, but I haven't gotten there yet.  -- AGD */
3668ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Xv currently disabled for crtc2.\n");
3669ab47cfaaSmrg	else
3670ab47cfaaSmrg	    SavageInitVideo( pScreen );
3671ab47cfaaSmrg    }
3672ab47cfaaSmrg#endif
3673ab47cfaaSmrg
3674ab47cfaaSmrg#ifdef XF86DRI
3675ab47cfaaSmrg    if ((psav->directRenderingEnabled) && (!psav->bDisableXvMC)) {
3676ab47cfaaSmrg        if (SAVAGEInitMC(pScreen))
3677ab47cfaaSmrg            xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is enabled\n");
3678ab47cfaaSmrg        else
3679ab47cfaaSmrg            xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"XvMC is not enabled\n");
3680ab47cfaaSmrg    }
3681ab47cfaaSmrg#endif
3682ab47cfaaSmrg
3683ab47cfaaSmrg    if (serverGeneration == 1)
3684ab47cfaaSmrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
3685ab47cfaaSmrg
3686ab47cfaaSmrg    return TRUE;
3687ab47cfaaSmrg}
3688ab47cfaaSmrg
3689ab47cfaaSmrg
3690ab47cfaaSmrgstatic int SavageInternalScreenInit(int scrnIndex, ScreenPtr pScreen)
3691ab47cfaaSmrg{
3692ab47cfaaSmrg    int ret = TRUE;
3693ab47cfaaSmrg    ScrnInfoPtr pScrn;
3694ab47cfaaSmrg    SavagePtr psav;
3695ab47cfaaSmrg    int width, height, displayWidth;
3696ab47cfaaSmrg    unsigned char *FBStart;
3697ab47cfaaSmrg
3698ab47cfaaSmrg    TRACE(("SavageInternalScreenInit()\n"));
3699ab47cfaaSmrg
3700ab47cfaaSmrg    pScrn = xf86Screens[pScreen->myNum];
3701ab47cfaaSmrg    psav = SAVPTR(pScrn);
3702ab47cfaaSmrg
3703ab47cfaaSmrg    displayWidth = pScrn->displayWidth;
3704ab47cfaaSmrg
3705ab47cfaaSmrg    if (psav->rotate) {
3706ab47cfaaSmrg	height = pScrn->virtualX;
3707ab47cfaaSmrg	width = pScrn->virtualY;
3708ab47cfaaSmrg    } else {
3709ab47cfaaSmrg	width = pScrn->virtualX;
3710ab47cfaaSmrg	height = pScrn->virtualY;
3711ab47cfaaSmrg    }
3712ab47cfaaSmrg
3713ab47cfaaSmrg
3714ab47cfaaSmrg    if(psav->shadowFB) {
3715ab47cfaaSmrg	psav->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
3716ab47cfaaSmrg	psav->ShadowPtr = xalloc(psav->ShadowPitch * height);
3717ab47cfaaSmrg	displayWidth = psav->ShadowPitch / (pScrn->bitsPerPixel >> 3);
3718ab47cfaaSmrg	FBStart = psav->ShadowPtr;
3719ab47cfaaSmrg    } else {
3720ab47cfaaSmrg	psav->ShadowPtr = NULL;
3721ab47cfaaSmrg	FBStart = psav->FBStart;
3722ab47cfaaSmrg    }
3723ab47cfaaSmrg
3724ab47cfaaSmrg    if (!psav->FBStart2nd) {
3725ab47cfaaSmrg
3726ab47cfaaSmrg        ret = fbScreenInit(pScreen, FBStart, width, height,
3727ab47cfaaSmrg                           pScrn->xDpi, pScrn->yDpi,
3728ab47cfaaSmrg                           psav->ulAperturePitch / (pScrn->bitsPerPixel >> 3), /*displayWidth,*/
3729ab47cfaaSmrg                           pScrn->bitsPerPixel);
3730ab47cfaaSmrg
3731ab47cfaaSmrg    } else {
3732ab47cfaaSmrg	FbOverlayScrPrivPtr pScrPriv;
3733ab47cfaaSmrg	int Depth2nd = DEPTH_2ND(pScrn);
3734ab47cfaaSmrg	if (!fbSetupScreen (pScreen, FBStart, width, height,
3735ab47cfaaSmrg			    pScrn->xDpi, pScrn->yDpi, displayWidth, 8))
3736ab47cfaaSmrg	    return FALSE;
3737ab47cfaaSmrg	if (pScrn->depth == 8) {
3738ab47cfaaSmrg	    ret = fbOverlayFinishScreenInit (pScreen, FBStart,
3739ab47cfaaSmrg					     psav->FBStart2nd, width,
3740ab47cfaaSmrg					     height,pScrn->xDpi, pScrn->yDpi,
3741ab47cfaaSmrg					     displayWidth,displayWidth,
3742ab47cfaaSmrg					     8, DEPTH_BPP(Depth2nd),
3743ab47cfaaSmrg					     8, Depth2nd);
3744ab47cfaaSmrg	    pScrPriv = fbOverlayGetScrPriv(pScreen);
3745ab47cfaaSmrg	    pScrPriv->layer[0].key = pScrn->colorKey;
3746ab47cfaaSmrg	} else {
3747ab47cfaaSmrg	    ret = fbOverlayFinishScreenInit (pScreen, psav->FBStart2nd,
3748ab47cfaaSmrg					     FBStart,
3749ab47cfaaSmrg					     width, height,pScrn->xDpi,
3750ab47cfaaSmrg					     pScrn->yDpi,
3751ab47cfaaSmrg					     displayWidth,displayWidth,
3752ab47cfaaSmrg					     DEPTH_BPP(Depth2nd), 8,
3753ab47cfaaSmrg					     Depth2nd, 8);
3754ab47cfaaSmrg	    pScrPriv = fbOverlayGetScrPriv(pScreen);
3755ab47cfaaSmrg	    pScrPriv->layer[1].key = pScrn->colorKey;
3756ab47cfaaSmrg	}
3757ab47cfaaSmrg    }
3758ab47cfaaSmrg    return ret;
3759ab47cfaaSmrg}
3760ab47cfaaSmrg
3761ab47cfaaSmrg
3762ab47cfaaSmrgstatic int SavageGetRefresh(DisplayModePtr mode)
3763ab47cfaaSmrg{
3764ab47cfaaSmrg    int refresh = (mode->Clock * 1000) / (mode->HTotal * mode->VTotal);
3765ab47cfaaSmrg    if (mode->Flags & V_INTERLACE)
3766ab47cfaaSmrg	refresh *= 2.0;
3767ab47cfaaSmrg    if (mode->Flags & V_DBLSCAN)
3768ab47cfaaSmrg	refresh /= 2.0;
3769ab47cfaaSmrg    if (mode->VScan > 1)
3770ab47cfaaSmrg	refresh /= mode->VScan;
3771ab47cfaaSmrg    return refresh;
3772ab47cfaaSmrg}
3773ab47cfaaSmrg
3774ab47cfaaSmrg
3775ab47cfaaSmrgstatic ModeStatus SavageValidMode(int index, DisplayModePtr pMode,
3776ab47cfaaSmrg				  Bool verbose, int flags)
3777ab47cfaaSmrg{
3778ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[index];
3779ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
3780ab47cfaaSmrg    int refresh;
3781ab47cfaaSmrg
3782ab47cfaaSmrg    TRACE(("SavageValidMode\n"));
3783ab47cfaaSmrg
3784ab47cfaaSmrg    /* We prohibit modes bigger than the LCD panel. */
3785ab47cfaaSmrg    /* TODO We should do this only if the panel is active. */
3786ab47cfaaSmrg
3787ab47cfaaSmrg    if( psav->TvOn )
3788ab47cfaaSmrg    {
3789ab47cfaaSmrg	if( pMode->HDisplay > psav->TVSizeX )
3790ab47cfaaSmrg	    return MODE_VIRTUAL_X;
3791ab47cfaaSmrg
3792ab47cfaaSmrg	if( pMode->VDisplay > psav->TVSizeY )
3793ab47cfaaSmrg	    return MODE_VIRTUAL_Y;
3794ab47cfaaSmrg
3795ab47cfaaSmrg    }
3796ab47cfaaSmrg
3797ab47cfaaSmrg    if((psav->DisplayType == MT_LCD) &&
3798ab47cfaaSmrg      ((pMode->HDisplay > psav->PanelX) ||
3799ab47cfaaSmrg       (pMode->VDisplay > psav->PanelY)))
3800ab47cfaaSmrg	    return MODE_PANEL;
3801ab47cfaaSmrg
3802ab47cfaaSmrg    if (psav->UseBIOS) {
3803ab47cfaaSmrg	refresh = SavageGetRefresh(pMode);
3804ab47cfaaSmrg        return (SavageMatchBiosMode(pScrn,pMode->HDisplay,
3805ab47cfaaSmrg                                   pMode->VDisplay,
3806ab47cfaaSmrg                                   refresh,NULL,NULL));
3807ab47cfaaSmrg    }
3808ab47cfaaSmrg
3809ab47cfaaSmrg    return MODE_OK;
3810ab47cfaaSmrg}
3811ab47cfaaSmrg
3812ab47cfaaSmrgstatic Bool SavageModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
3813ab47cfaaSmrg{
3814ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
3815ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
3816ab47cfaaSmrg    int width, dclk, i, j; /*, refresh; */
3817ab47cfaaSmrg    unsigned int m, n, r;
3818ab47cfaaSmrg    unsigned char tmp = 0;
3819ab47cfaaSmrg    SavageRegPtr new = &psav->ModeReg;
3820ab47cfaaSmrg    vgaRegPtr vganew = &hwp->ModeReg;
3821ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
3822ab47cfaaSmrg    int refresh;
3823ab47cfaaSmrg    unsigned int newmode=0, newrefresh=0;
3824ab47cfaaSmrg
3825ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
3826ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
3827ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
3828ab47cfaaSmrg
3829ab47cfaaSmrg    TRACE(("SavageModeInit(%dx%d, %dHz)\n",
3830ab47cfaaSmrg	mode->HDisplay, mode->VDisplay, mode->Clock));
3831ab47cfaaSmrg
3832ab47cfaaSmrg#if 0
3833ab47cfaaSmrg    ErrorF("Clock = %d, HDisplay = %d, HSStart = %d\n",
3834ab47cfaaSmrg	    mode->Clock, mode->HDisplay, mode->HSyncStart);
3835ab47cfaaSmrg    ErrorF("HSEnd = %d, HSkew = %d\n",
3836ab47cfaaSmrg	    mode->HSyncEnd, mode->HSkew);
3837ab47cfaaSmrg    ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n",
3838ab47cfaaSmrg	    mode->VDisplay, mode->VSyncStart, mode->VSyncEnd);
3839ab47cfaaSmrg    ErrorF("VTotal = %d\n",
3840ab47cfaaSmrg	    mode->VTotal);
3841ab47cfaaSmrg    ErrorF("HDisplay = %d, HSStart = %d\n",
3842ab47cfaaSmrg	    mode->CrtcHDisplay, mode->CrtcHSyncStart);
3843ab47cfaaSmrg    ErrorF("HSEnd = %d, HSkey = %d\n",
3844ab47cfaaSmrg	    mode->CrtcHSyncEnd, mode->CrtcHSkew);
3845ab47cfaaSmrg    ErrorF("VDisplay - %d, VSStart = %d, VSEnd = %d\n",
3846ab47cfaaSmrg	    mode->CrtcVDisplay, mode->CrtcVSyncStart, mode->CrtcVSyncEnd);
3847ab47cfaaSmrg    ErrorF("VTotal = %d\n",
3848ab47cfaaSmrg	    mode->CrtcVTotal);
3849ab47cfaaSmrg#endif
3850ab47cfaaSmrg
3851ab47cfaaSmrg    if (psav->IsSecondary) {
3852ab47cfaaSmrg	refresh = SavageGetRefresh(mode);
3853ab47cfaaSmrg
3854ab47cfaaSmrg        SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh,
3855ab47cfaaSmrg                            &newmode,&newrefresh);
3856ab47cfaaSmrg	new->mode = newmode;
3857ab47cfaaSmrg	new->refresh = newrefresh;
3858ab47cfaaSmrg
3859ab47cfaaSmrg        /* do it! */
3860ab47cfaaSmrg        SavageWriteMode(pScrn, vganew, new, TRUE);
3861ab47cfaaSmrg
3862ab47cfaaSmrg        if (psav->FBStart2nd) {
3863ab47cfaaSmrg	    SavageStreamsOn(pScrn);
3864ab47cfaaSmrg	    SavageInitSecondaryStream(pScrn);
3865ab47cfaaSmrg        }
3866ab47cfaaSmrg
3867ab47cfaaSmrg        SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
3868ab47cfaaSmrg	return TRUE;
3869ab47cfaaSmrg    }
3870ab47cfaaSmrg
3871ab47cfaaSmrg
3872ab47cfaaSmrg    if (pScrn->bitsPerPixel == 8)
3873ab47cfaaSmrg	psav->HorizScaleFactor = 1;
3874ab47cfaaSmrg    else if (pScrn->bitsPerPixel == 16)
3875ab47cfaaSmrg	psav->HorizScaleFactor = 1;	/* I don't think we ever want 2 */
3876ab47cfaaSmrg    else
3877ab47cfaaSmrg	psav->HorizScaleFactor = 1;
3878ab47cfaaSmrg
3879ab47cfaaSmrg    if (psav->HorizScaleFactor == 2)
3880ab47cfaaSmrg	if (!mode->CrtcHAdjusted) {
3881ab47cfaaSmrg	    mode->CrtcHDisplay *= 2;
3882ab47cfaaSmrg	    mode->CrtcHSyncStart *= 2;
3883ab47cfaaSmrg	    mode->CrtcHSyncEnd *= 2;
3884ab47cfaaSmrg	    mode->CrtcHBlankStart *= 2;
3885ab47cfaaSmrg	    mode->CrtcHBlankEnd *= 2;
3886ab47cfaaSmrg	    mode->CrtcHTotal *= 2;
3887ab47cfaaSmrg	    mode->CrtcHSkew *= 2;
3888ab47cfaaSmrg	    mode->CrtcHAdjusted = TRUE;
3889ab47cfaaSmrg	}
3890ab47cfaaSmrg
3891ab47cfaaSmrg    if (!vgaHWInit(pScrn, mode))
3892ab47cfaaSmrg	return FALSE;
3893ab47cfaaSmrg
3894ab47cfaaSmrg    new->mode = 0;
3895ab47cfaaSmrg
3896ab47cfaaSmrg    /* We need to set CR67 whether or not we use the BIOS. */
3897ab47cfaaSmrg
3898ab47cfaaSmrg    dclk = mode->Clock;
3899ab47cfaaSmrg    new->CR67 = 0x00;
3900ab47cfaaSmrg
3901ab47cfaaSmrg    switch( pScrn->depth ) {
3902ab47cfaaSmrg    case 8:
3903ab47cfaaSmrg	if( (psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000) )
3904ab47cfaaSmrg	    new->CR67 = 0x10;	/* 8bpp, 2 pixels/clock */
3905ab47cfaaSmrg	else
3906ab47cfaaSmrg	    new->CR67 = 0x00;	/* 8bpp, 1 pixel/clock */
3907ab47cfaaSmrg	break;
3908ab47cfaaSmrg    case 15:
3909ab47cfaaSmrg	if(
3910ab47cfaaSmrg	    S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
3911ab47cfaaSmrg	    ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000))
3912ab47cfaaSmrg	)
3913ab47cfaaSmrg	    new->CR67 = 0x30;	/* 15bpp, 2 pixel/clock */
3914ab47cfaaSmrg	else
3915ab47cfaaSmrg	    new->CR67 = 0x20;	/* 15bpp, 1 pixels/clock */
3916ab47cfaaSmrg	break;
3917ab47cfaaSmrg    case 16:
3918ab47cfaaSmrg	if(
3919ab47cfaaSmrg	    S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ||
3920ab47cfaaSmrg	    ((psav->Chipset == S3_SAVAGE2000) && (dclk >= 230000))
3921ab47cfaaSmrg	)
3922ab47cfaaSmrg	    new->CR67 = 0x50;	/* 16bpp, 2 pixel/clock */
3923ab47cfaaSmrg	else
3924ab47cfaaSmrg	    new->CR67 = 0x40;	/* 16bpp, 1 pixels/clock */
3925ab47cfaaSmrg	break;
3926ab47cfaaSmrg    case 24:
3927ab47cfaaSmrg	if (psav->primStreamBpp == 24 )
3928ab47cfaaSmrg	    new->CR67 = 0x70;
3929ab47cfaaSmrg	else
3930ab47cfaaSmrg	    new->CR67 = 0xd0;
3931ab47cfaaSmrg	break;
3932ab47cfaaSmrg    }
3933ab47cfaaSmrg
3934ab47cfaaSmrg
3935ab47cfaaSmrg    if( psav->UseBIOS ) {
3936ab47cfaaSmrg	int refresh;
3937ab47cfaaSmrg	unsigned int newmode=0, newrefresh=0;
3938ab47cfaaSmrg
3939ab47cfaaSmrg	refresh = SavageGetRefresh(mode);
3940ab47cfaaSmrg
3941ab47cfaaSmrg        SavageMatchBiosMode(pScrn,mode->HDisplay,mode->VDisplay,refresh,
3942ab47cfaaSmrg                            &newmode,&newrefresh);
3943ab47cfaaSmrg	new->mode = newmode;
3944ab47cfaaSmrg	new->refresh = newrefresh;
3945ab47cfaaSmrg    }
3946ab47cfaaSmrg
3947ab47cfaaSmrg    if( !new->mode ) {
3948ab47cfaaSmrg	/*
3949ab47cfaaSmrg	 * Either BIOS use is disabled, or we failed to find a suitable
3950ab47cfaaSmrg	 * match.  Fall back to traditional register-crunching.
3951ab47cfaaSmrg	 */
3952ab47cfaaSmrg
3953ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x3a);
3954ab47cfaaSmrg	tmp = VGAIN8(vgaCRReg);
3955ab47cfaaSmrg	if (psav->pci_burst)
3956ab47cfaaSmrg	    new->CR3A = (tmp & 0x7f) | 0x15;
3957ab47cfaaSmrg	else
3958ab47cfaaSmrg	    new->CR3A = tmp | 0x95;
3959ab47cfaaSmrg
3960ab47cfaaSmrg	new->CR53 = 0x00;
3961ab47cfaaSmrg	new->CR31 = 0x8c;
3962ab47cfaaSmrg	new->CR66 = 0x89;
3963ab47cfaaSmrg
3964ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x58);
3965ab47cfaaSmrg	new->CR58 = VGAIN8(vgaCRReg) & 0x80;
3966ab47cfaaSmrg	new->CR58 |= 0x13;
3967ab47cfaaSmrg
3968ab47cfaaSmrg#if 0
3969ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x55);
3970ab47cfaaSmrg	new->CR55 = VGAIN8(vgaCRReg);
3971ab47cfaaSmrg	if (psav->hwcursor)
3972ab47cfaaSmrg		new->CR55 |= 0x10;
3973ab47cfaaSmrg#endif
3974ab47cfaaSmrg
3975ab47cfaaSmrg	new->SR15 = 0x03 | 0x80;
3976ab47cfaaSmrg	new->SR18 = 0x00;
3977ab47cfaaSmrg
3978ab47cfaaSmrg
3979ab47cfaaSmrg	/* enable gamma correction */
3980ab47cfaaSmrg	if( pScrn->depth == 24 )
3981ab47cfaaSmrg	    new->SR1B = 0x18;
3982ab47cfaaSmrg	else
3983ab47cfaaSmrg	    new->SR1B = 0x00;
3984ab47cfaaSmrg
3985ab47cfaaSmrg	/* set 8-bit CLUT */
3986ab47cfaaSmrg	new->SR1B |= 0x10;
3987ab47cfaaSmrg
3988ab47cfaaSmrg	new->CR43 = new->CR45 = new->CR65 = 0x00;
3989ab47cfaaSmrg
3990ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x40);
3991ab47cfaaSmrg	new->CR40 = VGAIN8(vgaCRReg) & ~0x01;
3992ab47cfaaSmrg
3993ab47cfaaSmrg	new->MMPR0 = 0x010400;
3994ab47cfaaSmrg	new->MMPR1 = 0x00;
3995ab47cfaaSmrg	new->MMPR2 = 0x0808;
3996ab47cfaaSmrg	new->MMPR3 = 0x08080810;
3997ab47cfaaSmrg
3998ab47cfaaSmrg	if (psav->fifo_aggressive || psav->fifo_moderate ||
3999ab47cfaaSmrg	    psav->fifo_conservative) {
4000ab47cfaaSmrg		new->MMPR1 = 0x0200;
4001ab47cfaaSmrg		new->MMPR2 = 0x1808;
4002ab47cfaaSmrg		new->MMPR3 = 0x08081810;
4003ab47cfaaSmrg	}
4004ab47cfaaSmrg
4005ab47cfaaSmrg	if (psav->MCLK <= 0) {
4006ab47cfaaSmrg		new->SR10 = 255;
4007ab47cfaaSmrg		new->SR11 = 255;
4008ab47cfaaSmrg	}
4009ab47cfaaSmrg
4010ab47cfaaSmrg	psav->NeedSTREAMS = FALSE;
4011ab47cfaaSmrg
4012ab47cfaaSmrg	SavageCalcClock(dclk, 1, 1, 127, 0, 4, 180000, 360000,
4013ab47cfaaSmrg			&m, &n, &r);
4014ab47cfaaSmrg	new->SR12 = (r << 6) | (n & 0x3f);
4015ab47cfaaSmrg	new->SR13 = m & 0xff;
4016ab47cfaaSmrg	new->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2;
4017ab47cfaaSmrg
4018ab47cfaaSmrg	if (psav->fifo_moderate) {
4019ab47cfaaSmrg	    if (psav->primStreamBpp < 24)
4020ab47cfaaSmrg		new->MMPR0 -= 0x8000;
4021ab47cfaaSmrg	    else
4022ab47cfaaSmrg		new->MMPR0 -= 0x4000;
4023ab47cfaaSmrg	} else if (psav->fifo_aggressive) {
4024ab47cfaaSmrg	    if (psav->primStreamBpp < 24)
4025ab47cfaaSmrg		new->MMPR0 -= 0xc000;
4026ab47cfaaSmrg	    else
4027ab47cfaaSmrg		new->MMPR0 -= 0x6000;
4028ab47cfaaSmrg	}
4029ab47cfaaSmrg
4030ab47cfaaSmrg	if (mode->Flags & V_INTERLACE)
4031ab47cfaaSmrg	    new->CR42 = 0x20;
4032ab47cfaaSmrg	else
4033ab47cfaaSmrg	    new->CR42 = 0x00;
4034ab47cfaaSmrg
4035ab47cfaaSmrg	new->CR34 = 0x10;
4036ab47cfaaSmrg
4037ab47cfaaSmrg	i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8) |
4038ab47cfaaSmrg	    ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) |
4039ab47cfaaSmrg	    ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) |
4040ab47cfaaSmrg	    ((mode->CrtcHSyncStart & 0x800) >> 7);
4041ab47cfaaSmrg
4042ab47cfaaSmrg	if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64)
4043ab47cfaaSmrg	    i |= 0x08;
4044ab47cfaaSmrg	if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32)
4045ab47cfaaSmrg	    i |= 0x20;
4046ab47cfaaSmrg	j = (vganew->CRTC[0] + ((i & 0x01) << 8) +
4047ab47cfaaSmrg	     vganew->CRTC[4] + ((i & 0x10) << 4) + 1) / 2;
4048ab47cfaaSmrg	if (j - (vganew->CRTC[4] + ((i & 0x10) << 4)) < 4) {
4049ab47cfaaSmrg	    if (vganew->CRTC[4] + ((i & 0x10) << 4) + 4 <=
4050ab47cfaaSmrg	        vganew->CRTC[0] + ((i & 0x01) << 8))
4051ab47cfaaSmrg		j = vganew->CRTC[4] + ((i & 0x10) << 4) + 4;
4052ab47cfaaSmrg	    else
4053ab47cfaaSmrg		j = vganew->CRTC[0] + ((i & 0x01) << 8) + 1;
4054ab47cfaaSmrg	}
4055ab47cfaaSmrg
4056ab47cfaaSmrg	new->CR3B = j & 0xff;
4057ab47cfaaSmrg	i |= (j & 0x100) >> 2;
4058ab47cfaaSmrg	new->CR3C = (vganew->CRTC[0] + ((i & 0x01) << 8))  / 2 ;
4059ab47cfaaSmrg	new->CR5D = i;
4060ab47cfaaSmrg	new->CR5E = (((mode->CrtcVTotal - 2) & 0x400) >> 10) |
4061ab47cfaaSmrg		    (((mode->CrtcVDisplay - 1) & 0x400) >> 9) |
4062ab47cfaaSmrg		    (((mode->CrtcVSyncStart) & 0x400) >> 8) |
4063ab47cfaaSmrg		    (((mode->CrtcVSyncStart) & 0x400) >> 6) | 0x40;
4064ab47cfaaSmrg	width = (pScrn->displayWidth * (psav->primStreamBpp / 8)) >> 3;
4065ab47cfaaSmrg	new->CR91 = vganew->CRTC[19] = 0xff & width;
4066ab47cfaaSmrg	new->CR51 = (0x300 & width) >> 4;
4067ab47cfaaSmrg	new->CR90 = 0x80 | (width >> 8);
4068ab47cfaaSmrg	vganew->MiscOutReg |= 0x0c;
4069ab47cfaaSmrg
4070ab47cfaaSmrg	/* Set frame buffer description. */
4071ab47cfaaSmrg
4072ab47cfaaSmrg	if (psav->primStreamBpp <= 8)
4073ab47cfaaSmrg	    new->CR50 = 0;
4074ab47cfaaSmrg	else if (psav->primStreamBpp <= 16)
4075ab47cfaaSmrg	    new->CR50 = 0x10;
4076ab47cfaaSmrg	else
4077ab47cfaaSmrg	    new->CR50 = 0x30;
4078ab47cfaaSmrg
4079ab47cfaaSmrg	if (pScrn->displayWidth == 640)
4080ab47cfaaSmrg	    new->CR50 |= 0x40;
4081ab47cfaaSmrg	else if (pScrn->displayWidth == 800)
4082ab47cfaaSmrg	    new->CR50 |= 0x80;
4083ab47cfaaSmrg	else if (pScrn->displayWidth == 1024)
4084ab47cfaaSmrg	    new->CR50 |= 0x00;
4085ab47cfaaSmrg	else if (pScrn->displayWidth == 1152)
4086ab47cfaaSmrg	    new->CR50 |= 0x01;
4087ab47cfaaSmrg	else if (pScrn->displayWidth == 1280)
4088ab47cfaaSmrg	    new->CR50 |= 0xc0;
4089ab47cfaaSmrg	else if (pScrn->displayWidth == 1600)
4090ab47cfaaSmrg	    new->CR50 |= 0x81;
4091ab47cfaaSmrg	else
4092ab47cfaaSmrg	    new->CR50 |= 0xc1;	/* Use GBD */
4093ab47cfaaSmrg
4094ab47cfaaSmrg	if( S3_SAVAGE_MOBILE_SERIES(psav->Chipset) )
4095ab47cfaaSmrg	    new->CR33 = 0x00;
4096ab47cfaaSmrg	else
4097ab47cfaaSmrg	    new->CR33 = 0x08;
4098ab47cfaaSmrg
4099ab47cfaaSmrg	vganew->CRTC[0x17] = 0xeb;
4100ab47cfaaSmrg
4101ab47cfaaSmrg	new->CR67 |= 1;
4102ab47cfaaSmrg
4103ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x36);
4104ab47cfaaSmrg	new->CR36 = VGAIN8(vgaCRReg);
4105ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x68);
4106ab47cfaaSmrg	new->CR68 = VGAIN8(vgaCRReg);
4107ab47cfaaSmrg
4108ab47cfaaSmrg	new->CR69 = 0;
4109ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x6f);
4110ab47cfaaSmrg	new->CR6F = VGAIN8(vgaCRReg);
4111ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x86);
4112ab47cfaaSmrg	new->CR86 = VGAIN8(vgaCRReg) | 0x08;
4113ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x88);
4114ab47cfaaSmrg	new->CR88 = VGAIN8(vgaCRReg) | DISABLE_BLOCK_WRITE_2D;
4115ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0xb0);
4116ab47cfaaSmrg	new->CRB0 = VGAIN8(vgaCRReg) | 0x80;
4117ab47cfaaSmrg    }
4118ab47cfaaSmrg
4119ab47cfaaSmrg    pScrn->vtSema = TRUE;
4120ab47cfaaSmrg
4121ab47cfaaSmrg    /* do it! */
4122ab47cfaaSmrg    SavageWriteMode(pScrn, vganew, new, TRUE);
4123ab47cfaaSmrg
4124ab47cfaaSmrg    if (psav->FBStart2nd) {
4125ab47cfaaSmrg        SavageStreamsOn(pScrn);
4126ab47cfaaSmrg	SavageInitSecondaryStream(pScrn);
4127ab47cfaaSmrg    }
4128ab47cfaaSmrg
4129ab47cfaaSmrg    SavageAdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
4130ab47cfaaSmrg
4131ab47cfaaSmrg    return TRUE;
4132ab47cfaaSmrg}
4133ab47cfaaSmrg
4134ab47cfaaSmrg
4135ab47cfaaSmrgstatic Bool SavageCloseScreen(int scrnIndex, ScreenPtr pScreen)
4136ab47cfaaSmrg{
4137ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4138ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
4139ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4140ab47cfaaSmrg    vgaRegPtr vgaSavePtr = &hwp->SavedReg;
4141ab47cfaaSmrg    SavageRegPtr SavageSavePtr = &psav->SavedReg;
4142ab47cfaaSmrg
4143ab47cfaaSmrg    TRACE(("SavageCloseScreen\n"));
4144ab47cfaaSmrg
4145ab47cfaaSmrg#ifdef XF86DRI
4146ab47cfaaSmrg    if (psav->directRenderingEnabled) {
4147ab47cfaaSmrg        SAVAGEDRICloseScreen(pScreen);
4148ab47cfaaSmrg	/* reset shadow values */
4149ab47cfaaSmrg	SavageInitShadowStatus(pScrn);
4150ab47cfaaSmrg        psav->directRenderingEnabled=FALSE;
4151ab47cfaaSmrg    }
4152ab47cfaaSmrg#endif
4153ab47cfaaSmrg
4154ab47cfaaSmrg    if (psav->EXADriverPtr) {
4155ab47cfaaSmrg	exaDriverFini(pScreen);
4156ab47cfaaSmrg	psav->EXADriverPtr = NULL;
4157ab47cfaaSmrg    }
4158ab47cfaaSmrg
4159ab47cfaaSmrg    if( psav->AccelInfoRec ) {
4160ab47cfaaSmrg        XAADestroyInfoRec( psav->AccelInfoRec );
4161ab47cfaaSmrg	psav->AccelInfoRec = NULL;
4162ab47cfaaSmrg    }
4163ab47cfaaSmrg
4164ab47cfaaSmrg    if( psav->DGAModes ) {
4165ab47cfaaSmrg	xfree( psav->DGAModes );
4166ab47cfaaSmrg	psav->DGAModes = NULL;
4167ab47cfaaSmrg	psav->numDGAModes = 0;
4168ab47cfaaSmrg    }
4169ab47cfaaSmrg
4170ab47cfaaSmrg    if (pScrn->vtSema) {
4171ab47cfaaSmrg        if (psav->FBStart2nd)
4172ab47cfaaSmrg	    SavageStreamsOff(pScrn);
4173ab47cfaaSmrg	SavageWriteMode(pScrn, vgaSavePtr, SavageSavePtr, FALSE);
4174ab47cfaaSmrg        SavageResetStreams(pScrn);
4175ab47cfaaSmrg	vgaHWLock(hwp);
4176ab47cfaaSmrg	SavageUnmapMem(pScrn, 0);
4177ab47cfaaSmrg    }
4178ab47cfaaSmrg
4179ab47cfaaSmrg    if (psav->pVbe)
4180ab47cfaaSmrg      vbeFree(psav->pVbe);
4181ab47cfaaSmrg    psav->pVbe = NULL;
4182ab47cfaaSmrg
4183ab47cfaaSmrg    pScrn->vtSema = FALSE;
4184ab47cfaaSmrg    pScreen->CloseScreen = psav->CloseScreen;
4185ab47cfaaSmrg
4186ab47cfaaSmrg    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
4187ab47cfaaSmrg}
4188ab47cfaaSmrg
4189ab47cfaaSmrg
4190ab47cfaaSmrgstatic Bool SavageSaveScreen(ScreenPtr pScreen, int mode)
4191ab47cfaaSmrg{
4192ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
4193ab47cfaaSmrg
4194ab47cfaaSmrg    TRACE(("SavageSaveScreen(0x%x)\n", mode));
4195ab47cfaaSmrg
4196ab47cfaaSmrg    if( pScrn->vtSema && SAVPTR(pScrn)->hwcursor && SAVPTR(pScrn)->hwc_on )
4197ab47cfaaSmrg    {
4198ab47cfaaSmrg	if( xf86IsUnblank(mode) )
4199ab47cfaaSmrg	    SavageShowCursor( pScrn );
4200ab47cfaaSmrg	else
4201ab47cfaaSmrg	    SavageHideCursor( pScrn );
4202ab47cfaaSmrg	SAVPTR(pScrn)->hwc_on = TRUE; /*restore */
4203ab47cfaaSmrg    }
4204ab47cfaaSmrg
4205ab47cfaaSmrg    return vgaHWSaveScreen(pScreen, mode);
4206ab47cfaaSmrg}
4207ab47cfaaSmrg
4208ab47cfaaSmrgvoid SavageAdjustFrame(int scrnIndex, int x, int y, int flags)
4209ab47cfaaSmrg{
4210ab47cfaaSmrg    ScrnInfoPtr    pScrn      = xf86Screens[scrnIndex];
4211ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4212ab47cfaaSmrg
4213ab47cfaaSmrg    if (psav->IsSecondary) {
4214ab47cfaaSmrg	SavageDoAdjustFrame(pScrn, x, y, TRUE);
4215ab47cfaaSmrg    } else {
4216ab47cfaaSmrg	SavageDoAdjustFrame(pScrn, x, y, FALSE);
4217ab47cfaaSmrg    }
4218ab47cfaaSmrg
4219ab47cfaaSmrg}
4220ab47cfaaSmrg
4221ab47cfaaSmrgvoid
4222ab47cfaaSmrgSavageDoAdjustFrame(ScrnInfoPtr pScrn, int x, int y, int crtc2)
4223ab47cfaaSmrg{
4224ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4225ab47cfaaSmrg    int address=0,top=0,left=0,tile_height,tile_size;
4226ab47cfaaSmrg
4227ab47cfaaSmrg    TRACE(("SavageDoAdjustFrame(%d,%d,%x)\n", x, y, flags));
4228ab47cfaaSmrg
4229ab47cfaaSmrg    if (psav->Chipset == S3_SAVAGE2000) {
4230ab47cfaaSmrg        tile_height = TILEHEIGHT_2000; /* 32 */
4231ab47cfaaSmrg        tile_size = TILE_SIZE_BYTE_2000; /* 4096 */
4232ab47cfaaSmrg    } else {
4233ab47cfaaSmrg        tile_height = TILEHEIGHT; /* 16 */
4234ab47cfaaSmrg        tile_size = TILE_SIZE_BYTE; /* 2048 */
4235ab47cfaaSmrg    }
4236ab47cfaaSmrg
4237ab47cfaaSmrg    if (!psav->bTiled) {
4238ab47cfaaSmrg        left = x - x % 64;
4239ab47cfaaSmrg        top = y;
4240ab47cfaaSmrg        address = (top * psav->lDelta) + left * (pScrn->bitsPerPixel >> 3);
4241ab47cfaaSmrg        address = (address >> 5) << 5;
4242ab47cfaaSmrg    } else {
4243ab47cfaaSmrg        top = y - y % tile_height;
4244ab47cfaaSmrg        if (pScrn->bitsPerPixel == 16) {
4245ab47cfaaSmrg            left = x - x % TILEWIDTH_16BPP;
4246ab47cfaaSmrg            address = top * psav->lDelta + left * tile_size / TILEWIDTH_16BPP;
4247ab47cfaaSmrg        } else if (pScrn->bitsPerPixel == 32) {
4248ab47cfaaSmrg            left = x - x % TILEWIDTH_32BPP;
4249ab47cfaaSmrg            address = top * psav->lDelta + left * tile_size / TILEWIDTH_32BPP;
4250ab47cfaaSmrg        }
4251ab47cfaaSmrg    }
4252ab47cfaaSmrg
4253ab47cfaaSmrg    address += pScrn->fbOffset;
4254ab47cfaaSmrg
4255ab47cfaaSmrg    if (psav->Chipset == S3_SAVAGE_MX) {
4256ab47cfaaSmrg	if (!crtc2) {
4257ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR0, address & 0xFFFFFFFC);
4258ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFFC);/* IGA1 */
4259ab47cfaaSmrg        } else {
4260ab47cfaaSmrg            OUTREG32(PRI_STREAM2_FBUF_ADDR0, address & 0xFFFFFFFC);/* IGA2 */
4261ab47cfaaSmrg            OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFFC);
4262ab47cfaaSmrg	}
4263ab47cfaaSmrg    } else if (psav->Chipset == S3_SUPERSAVAGE) {
4264ab47cfaaSmrg	if (!crtc2) {
4265ab47cfaaSmrg            /* IGA1 */
4266ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR0, 0x80000000);
4267ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR1, address & 0xFFFFFFF8);
4268ab47cfaaSmrg        } else {
4269ab47cfaaSmrg            /* IGA2 */
4270ab47cfaaSmrg            OUTREG32(PRI_STREAM2_FBUF_ADDR0, ((address & 0xFFFFFFF8) | 0x80000000));
4271ab47cfaaSmrg            OUTREG32(PRI_STREAM2_FBUF_ADDR1, address & 0xFFFFFFF8);
4272ab47cfaaSmrg	}
4273ab47cfaaSmrg    } else if (psav->Chipset == S3_SAVAGE2000) {
4274ab47cfaaSmrg        /*  certain Y values seems to cause havoc, not sure why */
4275ab47cfaaSmrg        OUTREG32(PRI_STREAM_FBUF_ADDR0, (address & 0xFFFFFFF8));
4276ab47cfaaSmrg        OUTREG32(PRI_STREAM2_FBUF_ADDR0, (address & 0xFFFFFFF8));
4277ab47cfaaSmrg    } else {
4278ab47cfaaSmrg        OUTREG32(PRI_STREAM_FBUF_ADDR0,address |  0xFFFFFFFC);
4279ab47cfaaSmrg        OUTREG32(PRI_STREAM_FBUF_ADDR1,address |  0x80000000);
4280ab47cfaaSmrg    }
4281ab47cfaaSmrg
4282ab47cfaaSmrg    return;
4283ab47cfaaSmrg}
4284ab47cfaaSmrg
4285ab47cfaaSmrgBool SavageSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
4286ab47cfaaSmrg{
4287ab47cfaaSmrg    ScrnInfoPtr    pScrn      = xf86Screens[scrnIndex];
4288ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4289ab47cfaaSmrg    Bool success;
4290ab47cfaaSmrg
4291ab47cfaaSmrg    TRACE(("SavageSwitchMode\n"));
4292ab47cfaaSmrg
4293ab47cfaaSmrg    if (psav->FBStart2nd || (psav->videoFlags & VF_STREAMS_ON))
4294ab47cfaaSmrg        SavageStreamsOff(xf86Screens[scrnIndex]);
4295ab47cfaaSmrg
4296ab47cfaaSmrg    success = SavageModeInit(xf86Screens[scrnIndex], mode);
4297ab47cfaaSmrg
4298ab47cfaaSmrg    /* switching mode on primary will reset secondary.  it needs to be reset as well*/
4299ab47cfaaSmrg    if (psav->IsPrimary) {
4300ab47cfaaSmrg        DevUnion* pPriv;
4301ab47cfaaSmrg        SavageEntPtr pSavEnt;
4302ab47cfaaSmrg        pPriv = xf86GetEntityPrivate(pScrn->entityList[0],
4303ab47cfaaSmrg              gSavageEntityIndex);
4304ab47cfaaSmrg        pSavEnt = pPriv->ptr;
4305ab47cfaaSmrg        SavageModeInit(pSavEnt->pSecondaryScrn, pSavEnt->pSecondaryScrn->currentMode);
4306ab47cfaaSmrg    }
43078697ee19Smrg    SavagePanningCheck(pScrn, mode);
4308ab47cfaaSmrg
4309ab47cfaaSmrg    return success;
4310ab47cfaaSmrg}
4311ab47cfaaSmrg
4312ab47cfaaSmrg
4313ab47cfaaSmrgvoid SavageEnableMMIO(ScrnInfoPtr pScrn)
4314ab47cfaaSmrg{
4315ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
4316ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4317ab47cfaaSmrg    int vgaCRIndex, vgaCRReg;
4318ab47cfaaSmrg    unsigned char val;
4319ab47cfaaSmrg
4320ab47cfaaSmrg    TRACE(("SavageEnableMMIO\n"));
4321ab47cfaaSmrg
4322ab47cfaaSmrg    vgaHWSetStdFuncs(hwp);
4323ab47cfaaSmrg    vgaHWSetMmioFuncs(hwp, psav->MapBase, 0x8000);
4324ab47cfaaSmrg    val = VGAIN8(0x3c3);
4325ab47cfaaSmrg    VGAOUT8(0x3c3, val | 0x01);
4326ab47cfaaSmrg    val = VGAIN8(VGA_MISC_OUT_R);
4327ab47cfaaSmrg    VGAOUT8(VGA_MISC_OUT_W, val | 0x01);
4328ab47cfaaSmrg    vgaCRIndex = psav->vgaIOBase + 4;
4329ab47cfaaSmrg    vgaCRReg = psav->vgaIOBase + 5;
4330ab47cfaaSmrg
4331ab47cfaaSmrg    if( psav->Chipset >= S3_SAVAGE4 )
4332ab47cfaaSmrg    {
4333ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x40);
4334ab47cfaaSmrg	val = VGAIN8(vgaCRReg);
4335ab47cfaaSmrg	VGAOUT8(vgaCRReg, val | 1);
4336ab47cfaaSmrg    }
4337ab47cfaaSmrg
4338ab47cfaaSmrg    return;
4339ab47cfaaSmrg}
4340ab47cfaaSmrg
4341ab47cfaaSmrg
4342ab47cfaaSmrgvoid SavageDisableMMIO(ScrnInfoPtr pScrn)
4343ab47cfaaSmrg{
4344ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
4345ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4346ab47cfaaSmrg    int vgaCRIndex, vgaCRReg;
4347ab47cfaaSmrg    unsigned char val;
4348ab47cfaaSmrg
4349ab47cfaaSmrg    TRACE(("SavageDisableMMIO\n"));
4350ab47cfaaSmrg
4351ab47cfaaSmrg    vgaCRIndex = psav->vgaIOBase + 4;
4352ab47cfaaSmrg    vgaCRReg = psav->vgaIOBase + 5;
4353ab47cfaaSmrg
4354ab47cfaaSmrg    if( psav->Chipset >= S3_SAVAGE4 )
4355ab47cfaaSmrg    {
4356ab47cfaaSmrg	VGAOUT8(vgaCRIndex, 0x40);
4357ab47cfaaSmrg	val = VGAIN8(vgaCRReg);
4358ab47cfaaSmrg	VGAOUT8(vgaCRReg, val | 1);
4359ab47cfaaSmrg    }
4360ab47cfaaSmrg
4361ab47cfaaSmrg    vgaHWSetStdFuncs(hwp);
4362ab47cfaaSmrg
4363ab47cfaaSmrg    return;
4364ab47cfaaSmrg}
4365ab47cfaaSmrg
4366ab47cfaaSmrgvoid SavageLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
4367ab47cfaaSmrg		       LOCO *colors, VisualPtr pVisual)
4368ab47cfaaSmrg{
4369ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4370ab47cfaaSmrg    int i, index;
4371ab47cfaaSmrg    int updateKey = -1;
4372ab47cfaaSmrg    unsigned char byte = 0;
4373ab47cfaaSmrg
4374ab47cfaaSmrg    /* choose CLUT */
4375ab47cfaaSmrg    if (psav->IsPrimary) {
4376ab47cfaaSmrg	/* enable CLUT 1 */
4377ab47cfaaSmrg        VGAOUT8(0x3c4, 0x21);
4378ab47cfaaSmrg        byte = VGAIN8(0x3c5);
4379ab47cfaaSmrg        VGAOUT8(0x3c5, (byte & ~0x01));
4380ab47cfaaSmrg	/* select CLUT 1 */
4381ab47cfaaSmrg        VGAOUT8(0x3c4, 0x47);
4382ab47cfaaSmrg        byte = VGAIN8(0x3c5);
4383ab47cfaaSmrg        VGAOUT8(0x3c5, (byte & ~0x03) | 0x01); /* CLUT 1 */
4384ab47cfaaSmrg    } else if (psav->IsSecondary) {
4385ab47cfaaSmrg	/* enable CLUT 2 */
4386ab47cfaaSmrg        VGAOUT8(0x3c4, 0x21);
4387ab47cfaaSmrg        byte = VGAIN8(0x3c5);
4388ab47cfaaSmrg        VGAOUT8(0x3c5, (byte & ~0x10));
4389ab47cfaaSmrg	/* select CLUT 2 */
4390ab47cfaaSmrg        VGAOUT8(0x3c4, 0x47);
4391ab47cfaaSmrg        byte = VGAIN8(0x3c5);
4392ab47cfaaSmrg        VGAOUT8(0x3c5, (byte & ~0x03) | 0x02); /* CLUT 2 */
4393ab47cfaaSmrg    }
4394ab47cfaaSmrg
4395ab47cfaaSmrg    for (i=0; i<numColors; i++) {
4396ab47cfaaSmrg	index = indicies[i];
4397ab47cfaaSmrg	if (index == pScrn->colorKey) updateKey = index;
4398ab47cfaaSmrg	VGAOUT8(0x3c8, index);
4399ab47cfaaSmrg	VGAOUT8(0x3c9, colors[index].red);
4400ab47cfaaSmrg	VGAOUT8(0x3c9, colors[index].green);
4401ab47cfaaSmrg	VGAOUT8(0x3c9, colors[index].blue);
4402ab47cfaaSmrg    }
4403ab47cfaaSmrg
4404ab47cfaaSmrg    /* restore saved CLUT index value */
4405ab47cfaaSmrg    if (psav->IsPrimary || psav->IsSecondary) {
4406ab47cfaaSmrg        VGAOUT8(0x3c4, 0x47);
4407ab47cfaaSmrg        VGAOUT8(0x3c5, byte);
4408ab47cfaaSmrg    }
4409ab47cfaaSmrg
4410ab47cfaaSmrg    if (updateKey != -1)
4411ab47cfaaSmrg	SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green,
4412ab47cfaaSmrg			colors[updateKey].blue);
4413ab47cfaaSmrg}
4414ab47cfaaSmrg
4415ab47cfaaSmrg#define Shift(v,d)  ((d) < 0 ? ((v) >> (-d)) : ((v) << (d)))
4416ab47cfaaSmrg
4417ab47cfaaSmrgstatic void
4418ab47cfaaSmrgSavageUpdateKey(ScrnInfoPtr pScrn, int r, int g, int b)
4419ab47cfaaSmrg{
4420ab47cfaaSmrg    ScreenPtr pScreen;
4421ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4422ab47cfaaSmrg    FbOverlayScrPrivPtr pScrOvlPriv;
4423ab47cfaaSmrg    CARD32 key;
4424ab47cfaaSmrg    int ul = 0, ol = 1;
4425ab47cfaaSmrg
4426ab47cfaaSmrg    if (pScrn->depth != 8) {
4427ab47cfaaSmrg	ul = 1;
4428ab47cfaaSmrg	ol = 0;
4429ab47cfaaSmrg    }
4430ab47cfaaSmrg    if (!(pScreen = pScrn->pScreen)
4431ab47cfaaSmrg	|| !(pScrOvlPriv = fbOverlayGetScrPriv(pScreen)))
4432ab47cfaaSmrg	return;
4433ab47cfaaSmrg    key = ((Shift(r,psav->overlay.redShift) & psav->overlay.redMask)
4434ab47cfaaSmrg	   | (Shift(g,psav->overlay.greenShift) & psav->overlay.greenMask)
4435ab47cfaaSmrg	   | (Shift(b,psav->overlay.blueShift) & psav->overlay.blueMask));
4436ab47cfaaSmrg    if (pScrOvlPriv->layer[ol].key != key) {
4437ab47cfaaSmrg	pScrOvlPriv->layer[ol].key = key;
4438ab47cfaaSmrg	(*pScrOvlPriv->PaintKey) (&pScrOvlPriv->layer[ol].u.run.pixmap->drawable,
4439ab47cfaaSmrg				  &pScrOvlPriv->layer[ul].u.run.region,
4440ab47cfaaSmrg				  pScrOvlPriv->layer[ol].key, ol);
4441ab47cfaaSmrg    }
4442ab47cfaaSmrg}
4443ab47cfaaSmrg
4444ab47cfaaSmrg#if 0
4445ab47cfaaSmrg#define inStatus1() (hwp->readST01( hwp ))
4446ab47cfaaSmrg#endif
4447ab47cfaaSmrg
4448ab47cfaaSmrgvoid SavageLoadPaletteSavage4(ScrnInfoPtr pScrn, int numColors, int *indicies,
4449ab47cfaaSmrg		       LOCO *colors, VisualPtr pVisual)
4450ab47cfaaSmrg{
4451ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4452ab47cfaaSmrg    int i, index;
4453ab47cfaaSmrg    int updateKey = -1;
4454ab47cfaaSmrg
4455ab47cfaaSmrg    VerticalRetraceWait();
4456ab47cfaaSmrg
4457ab47cfaaSmrg    for (i=0; i<numColors; i++) {
4458ab47cfaaSmrg          if (!(inStatus1()) & 0x08)
4459ab47cfaaSmrg  	    VerticalRetraceWait();
4460ab47cfaaSmrg	index = indicies[i];
4461ab47cfaaSmrg	VGAOUT8(0x3c8, index);
4462ab47cfaaSmrg	VGAOUT8(0x3c9, colors[index].red);
4463ab47cfaaSmrg	VGAOUT8(0x3c9, colors[index].green);
4464ab47cfaaSmrg	VGAOUT8(0x3c9, colors[index].blue);
4465ab47cfaaSmrg	if (index == pScrn->colorKey) updateKey = index;
4466ab47cfaaSmrg    }
4467ab47cfaaSmrg    if (updateKey != -1)
4468ab47cfaaSmrg	SavageUpdateKey(pScrn, colors[updateKey].red, colors[updateKey].green,
4469ab47cfaaSmrg			colors[updateKey].blue);
4470ab47cfaaSmrg}
4471ab47cfaaSmrg
4472ab47cfaaSmrgstatic void SavageCalcClock(long freq, int min_m, int min_n1, int max_n1,
4473ab47cfaaSmrg			   int min_n2, int max_n2, long freq_min,
4474ab47cfaaSmrg			   long freq_max, unsigned int *mdiv,
4475ab47cfaaSmrg			   unsigned int *ndiv, unsigned int *r)
4476ab47cfaaSmrg{
4477ab47cfaaSmrg    double ffreq, ffreq_min, ffreq_max;
4478ab47cfaaSmrg    double div, diff, best_diff;
4479ab47cfaaSmrg    unsigned int m;
4480ab47cfaaSmrg    unsigned char n1, n2, best_n1=16+2, best_n2=2, best_m=125+2;
4481ab47cfaaSmrg
4482ab47cfaaSmrg    ffreq = freq / 1000.0 / BASE_FREQ;
4483ab47cfaaSmrg    ffreq_max = freq_max / 1000.0 / BASE_FREQ;
4484ab47cfaaSmrg    ffreq_min = freq_min / 1000.0 / BASE_FREQ;
4485ab47cfaaSmrg
4486ab47cfaaSmrg    if (ffreq < ffreq_min / (1 << max_n2)) {
4487ab47cfaaSmrg	    ErrorF("invalid frequency %1.3f Mhz\n",
4488ab47cfaaSmrg		   ffreq*BASE_FREQ);
4489ab47cfaaSmrg	    ffreq = ffreq_min / (1 << max_n2);
4490ab47cfaaSmrg    }
4491ab47cfaaSmrg    if (ffreq > ffreq_max / (1 << min_n2)) {
4492ab47cfaaSmrg	    ErrorF("invalid frequency %1.3f Mhz\n",
4493ab47cfaaSmrg		   ffreq*BASE_FREQ);
4494ab47cfaaSmrg	    ffreq = ffreq_max / (1 << min_n2);
4495ab47cfaaSmrg    }
4496ab47cfaaSmrg
4497ab47cfaaSmrg    /* work out suitable timings */
4498ab47cfaaSmrg
4499ab47cfaaSmrg    best_diff = ffreq;
4500ab47cfaaSmrg
4501ab47cfaaSmrg    for (n2=min_n2; n2<=max_n2; n2++) {
4502ab47cfaaSmrg	for (n1=min_n1+2; n1<=max_n1+2; n1++) {
4503ab47cfaaSmrg	    m = (int)(ffreq * n1 * (1 << n2) + 0.5);
4504ab47cfaaSmrg	    if (m < min_m+2 || m > 127+2)
4505ab47cfaaSmrg		continue;
4506ab47cfaaSmrg	    div = (double)(m) / (double)(n1);
4507ab47cfaaSmrg	    if ((div >= ffreq_min) &&
4508ab47cfaaSmrg		(div <= ffreq_max)) {
4509ab47cfaaSmrg		diff = ffreq - div / (1 << n2);
4510ab47cfaaSmrg		if (diff < 0.0)
4511ab47cfaaSmrg			diff = -diff;
4512ab47cfaaSmrg		if (diff < best_diff) {
4513ab47cfaaSmrg		    best_diff = diff;
4514ab47cfaaSmrg		    best_m = m;
4515ab47cfaaSmrg		    best_n1 = n1;
4516ab47cfaaSmrg		    best_n2 = n2;
4517ab47cfaaSmrg		}
4518ab47cfaaSmrg	    }
4519ab47cfaaSmrg	}
4520ab47cfaaSmrg    }
4521ab47cfaaSmrg
4522ab47cfaaSmrg    *ndiv = best_n1 - 2;
4523ab47cfaaSmrg    *r = best_n2;
4524ab47cfaaSmrg    *mdiv = best_m - 2;
4525ab47cfaaSmrg}
4526ab47cfaaSmrg
4527ab47cfaaSmrg
4528ab47cfaaSmrgvoid SavageGEReset(ScrnInfoPtr pScrn, int from_timeout, int line, char *file)
4529ab47cfaaSmrg{
4530ab47cfaaSmrg    unsigned char cr66;
4531ab47cfaaSmrg    int r, success = 0;
4532ab47cfaaSmrg    CARD32 fifo_control = 0, miu_control = 0;
4533ab47cfaaSmrg    CARD32 streams_timeout = 0, misc_timeout = 0;
4534ab47cfaaSmrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
4535ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4536ab47cfaaSmrg    int vgaCRIndex, vgaCRReg, vgaIOBase;
4537ab47cfaaSmrg
4538ab47cfaaSmrg    TRACE(("SavageGEReset(%d,%s)\n", line, file));
4539ab47cfaaSmrg
4540ab47cfaaSmrg    vgaIOBase = hwp->IOBase;
4541ab47cfaaSmrg    vgaCRIndex = vgaIOBase + 4;
4542ab47cfaaSmrg    vgaCRReg = vgaIOBase + 5;
4543ab47cfaaSmrg
4544ab47cfaaSmrg    if (from_timeout) {
4545ab47cfaaSmrg	if (psav->GEResetCnt++ < 10 || xf86GetVerbosity() > 1)
4546ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4547ab47cfaaSmrg		       "SavageGEReset called from %s line %d\n", file, line);
4548ab47cfaaSmrg    } else
4549ab47cfaaSmrg	psav->WaitIdleEmpty(psav);
4550ab47cfaaSmrg
4551ab47cfaaSmrg    if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) {
4552ab47cfaaSmrg	fifo_control = INREG(FIFO_CONTROL_REG);
4553ab47cfaaSmrg	miu_control = INREG(MIU_CONTROL_REG);
4554ab47cfaaSmrg	streams_timeout = INREG(STREAMS_TIMEOUT_REG);
4555ab47cfaaSmrg	misc_timeout = INREG(MISC_TIMEOUT_REG);
4556ab47cfaaSmrg    }
4557ab47cfaaSmrg
4558ab47cfaaSmrg    VGAOUT8(vgaCRIndex, 0x66);
4559ab47cfaaSmrg    cr66 = VGAIN8(vgaCRReg);
4560ab47cfaaSmrg
4561ab47cfaaSmrg    usleep(10000);
4562ab47cfaaSmrg    for (r=1; r<10; r++) {
4563ab47cfaaSmrg	VGAOUT8(vgaCRReg, cr66 | 0x02);
4564ab47cfaaSmrg	usleep(10000);
4565ab47cfaaSmrg	VGAOUT8(vgaCRReg, cr66 & ~0x02);
4566ab47cfaaSmrg	usleep(10000);
4567ab47cfaaSmrg
4568ab47cfaaSmrg	if (!from_timeout)
4569ab47cfaaSmrg	    psav->WaitIdleEmpty(psav);
4570ab47cfaaSmrg	OUTREG(DEST_SRC_STR, psav->Bpl << 16 | psav->Bpl);
4571ab47cfaaSmrg
4572ab47cfaaSmrg	usleep(10000);
4573ab47cfaaSmrg	switch(psav->Chipset) {
4574ab47cfaaSmrg	    case S3_SAVAGE3D:
4575ab47cfaaSmrg	    case S3_SAVAGE_MX:
4576ab47cfaaSmrg	      success = (STATUS_WORD0 & 0x0008ffff) == 0x00080000;
4577ab47cfaaSmrg	      break;
4578ab47cfaaSmrg	    case S3_SAVAGE4:
4579ab47cfaaSmrg	    case S3_PROSAVAGE:
4580ab47cfaaSmrg	    case S3_PROSAVAGEDDR:
4581ab47cfaaSmrg	    case S3_TWISTER:
4582ab47cfaaSmrg	    case S3_SUPERSAVAGE:
4583ab47cfaaSmrg	      success = (ALT_STATUS_WORD0 & 0x0081ffff) == 0x00800000;
4584ab47cfaaSmrg	      break;
4585ab47cfaaSmrg	    case S3_SAVAGE2000:
4586ab47cfaaSmrg	      success = (ALT_STATUS_WORD0 & 0x008fffff) == 0;
4587ab47cfaaSmrg	      break;
4588ab47cfaaSmrg	}
4589ab47cfaaSmrg	if(!success) {
4590ab47cfaaSmrg	    usleep(10000);
4591ab47cfaaSmrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4592ab47cfaaSmrg		"restarting S3 graphics engine reset %2d ...\n", r);
4593ab47cfaaSmrg	}
4594ab47cfaaSmrg	else
4595ab47cfaaSmrg	    break;
4596ab47cfaaSmrg    }
4597ab47cfaaSmrg
4598ab47cfaaSmrg    /* At this point, the FIFO is empty and the engine is idle. */
4599ab47cfaaSmrg
4600ab47cfaaSmrg    if (from_timeout && !S3_SAVAGE_MOBILE_SERIES(psav->Chipset) ) {
4601ab47cfaaSmrg	OUTREG(FIFO_CONTROL_REG, fifo_control);
4602ab47cfaaSmrg	OUTREG(MIU_CONTROL_REG, miu_control);
4603ab47cfaaSmrg	OUTREG(STREAMS_TIMEOUT_REG, streams_timeout);
4604ab47cfaaSmrg	OUTREG(MISC_TIMEOUT_REG, misc_timeout);
4605ab47cfaaSmrg    }
4606ab47cfaaSmrg
4607ab47cfaaSmrg    OUTREG(SRC_BASE, 0);
4608ab47cfaaSmrg    OUTREG(DEST_BASE, 0);
4609ab47cfaaSmrg    OUTREG(CLIP_L_R, ((0) << 16) | pScrn->displayWidth);
4610ab47cfaaSmrg    OUTREG(CLIP_T_B, ((0) << 16) | psav->ScissB);
4611ab47cfaaSmrg    OUTREG(MONO_PAT_0, ~0);
4612ab47cfaaSmrg    OUTREG(MONO_PAT_1, ~0);
4613ab47cfaaSmrg
4614ab47cfaaSmrg    SavageSetGBD(pScrn);
4615ab47cfaaSmrg
4616ab47cfaaSmrg}
4617ab47cfaaSmrg
4618ab47cfaaSmrg
4619ab47cfaaSmrg
4620ab47cfaaSmrg/* This function is used to debug, it prints out the contents of s3 regs */
4621ab47cfaaSmrg
4622ab47cfaaSmrgvoid
4623ab47cfaaSmrgSavagePrintRegs(ScrnInfoPtr pScrn)
4624ab47cfaaSmrg{
4625ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4626ab47cfaaSmrg    unsigned char i;
4627ab47cfaaSmrg    int vgaCRIndex = 0x3d4;
4628ab47cfaaSmrg    int vgaCRReg = 0x3d5;
4629ab47cfaaSmrg
4630ab47cfaaSmrg    ErrorF( "SR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" );
4631ab47cfaaSmrg
4632ab47cfaaSmrg    for( i = 0; i < 0x70; i++ ) {
4633ab47cfaaSmrg	if( !(i % 16) )
4634ab47cfaaSmrg	    ErrorF( "\nSR%xx ", i >> 4 );
4635ab47cfaaSmrg	VGAOUT8( 0x3c4, i );
4636ab47cfaaSmrg	ErrorF( " %02x", VGAIN8(0x3c5) );
4637ab47cfaaSmrg    }
4638ab47cfaaSmrg
4639ab47cfaaSmrg    ErrorF( "\n\nCR    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF" );
4640ab47cfaaSmrg
4641ab47cfaaSmrg    for( i = 0; i < 0xB7; i++ ) {
4642ab47cfaaSmrg	if( !(i % 16) )
4643ab47cfaaSmrg	    ErrorF( "\nCR%xx ", i >> 4 );
4644ab47cfaaSmrg	VGAOUT8( vgaCRIndex, i );
4645ab47cfaaSmrg	ErrorF( " %02x", VGAIN8(vgaCRReg) );
4646ab47cfaaSmrg    }
4647ab47cfaaSmrg
4648ab47cfaaSmrg    ErrorF("\n\n");
4649ab47cfaaSmrg}
4650ab47cfaaSmrg
4651ab47cfaaSmrgstatic void SavageDPMS(ScrnInfoPtr pScrn, int mode, int flags)
4652ab47cfaaSmrg{
4653ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4654ab47cfaaSmrg    unsigned char sr8 = 0x00, srd = 0x00;
4655ab47cfaaSmrg
4656ab47cfaaSmrg    TRACE(("SavageDPMS(%d,%x)\n", mode, flags));
4657ab47cfaaSmrg
4658ab47cfaaSmrg    if (psav->DisplayType == MT_CRT) {
4659ab47cfaaSmrg    	VGAOUT8(0x3c4, 0x08);
4660ab47cfaaSmrg    	sr8 = VGAIN8(0x3c5);
4661ab47cfaaSmrg    	sr8 |= 0x06;
4662ab47cfaaSmrg    	VGAOUT8(0x3c5, sr8);
4663ab47cfaaSmrg
4664ab47cfaaSmrg    	VGAOUT8(0x3c4, 0x0d);
4665ab47cfaaSmrg    	srd = VGAIN8(0x3c5);
4666ab47cfaaSmrg
4667ab47cfaaSmrg    	srd &= 0x03;
4668ab47cfaaSmrg
4669ab47cfaaSmrg    	switch (mode) {
4670ab47cfaaSmrg	    case DPMSModeOn:
4671ab47cfaaSmrg	    	break;
4672ab47cfaaSmrg	    case DPMSModeStandby:
4673ab47cfaaSmrg	    	srd |= 0x10;
4674ab47cfaaSmrg	    	break;
4675ab47cfaaSmrg	    case DPMSModeSuspend:
4676ab47cfaaSmrg	    	srd |= 0x40;
4677ab47cfaaSmrg	    	break;
4678ab47cfaaSmrg	    case DPMSModeOff:
4679ab47cfaaSmrg	    	srd |= 0x50;
4680ab47cfaaSmrg	    	break;
4681ab47cfaaSmrg	    default:
4682ab47cfaaSmrg	    	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode);
4683ab47cfaaSmrg	    	break;
4684ab47cfaaSmrg    	}
4685ab47cfaaSmrg
4686ab47cfaaSmrg    	VGAOUT8(0x3c4, 0x0d);
4687ab47cfaaSmrg    	VGAOUT8(0x3c5, srd);
4688ab47cfaaSmrg    }
4689ab47cfaaSmrg
4690ab47cfaaSmrg    if (psav->DisplayType == MT_LCD || psav->DisplayType == MT_DFP) {
4691ab47cfaaSmrg	if (S3_MOBILE_TWISTER_SERIES(psav->Chipset) && psav->UseBIOS) {
4692ab47cfaaSmrg	    SavageSetPanelEnabled(psav, (mode == DPMSModeOn));
4693ab47cfaaSmrg	} else {
4694ab47cfaaSmrg    	    switch (mode) {
4695ab47cfaaSmrg	        case DPMSModeOn:
4696ab47cfaaSmrg		    VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
4697ab47cfaaSmrg		    VGAOUT8(0x3c5, VGAIN8(0x3c5) | 0x10);
4698ab47cfaaSmrg	            break;
4699ab47cfaaSmrg	        case DPMSModeStandby:
4700ab47cfaaSmrg	        case DPMSModeSuspend:
4701ab47cfaaSmrg	        case DPMSModeOff:
4702ab47cfaaSmrg		    VGAOUT8(0x3c4, 0x31); /* SR31 bit 4 - FP enable */
4703ab47cfaaSmrg		    VGAOUT8(0x3c5, VGAIN8(0x3c5) & ~0x10);
4704ab47cfaaSmrg	            break;
4705ab47cfaaSmrg	        default:
4706ab47cfaaSmrg	            xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Invalid DPMS mode %d\n", mode);
4707ab47cfaaSmrg	            break;
4708ab47cfaaSmrg	    }
4709ab47cfaaSmrg        }
4710ab47cfaaSmrg    }
4711ab47cfaaSmrg
4712ab47cfaaSmrg    return;
4713ab47cfaaSmrg}
4714ab47cfaaSmrg
4715ab47cfaaSmrgstatic void
4716ab47cfaaSmrgSavageProbeDDC(ScrnInfoPtr pScrn, int index)
4717ab47cfaaSmrg{
4718ab47cfaaSmrg    vbeInfoPtr pVbe;
4719ab47cfaaSmrg
4720ab47cfaaSmrg    if (xf86LoadSubModule(pScrn, "vbe")) {
4721ab47cfaaSmrg	xf86LoaderReqSymLists(vbeSymbols, NULL);
4722ab47cfaaSmrg	pVbe = VBEInit(NULL, index);
4723ab47cfaaSmrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
4724ab47cfaaSmrg	vbeFree(pVbe);
4725ab47cfaaSmrg    }
4726ab47cfaaSmrg}
4727ab47cfaaSmrg
4728ab47cfaaSmrgstatic unsigned int
4729ab47cfaaSmrgSavageDDC1Read(ScrnInfoPtr pScrn)
4730ab47cfaaSmrg{
4731ab47cfaaSmrg    register unsigned char tmp;
4732ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4733ab47cfaaSmrg
4734ab47cfaaSmrg    UnLockExtRegs();
4735ab47cfaaSmrg
4736ab47cfaaSmrg    VerticalRetraceWait();
4737ab47cfaaSmrg
4738ab47cfaaSmrg    InI2CREG(tmp,psav->I2CPort);
4739ab47cfaaSmrg
4740ab47cfaaSmrg    return ((unsigned int) (tmp & 0x08));
4741ab47cfaaSmrg}
4742ab47cfaaSmrg
4743ab47cfaaSmrgstatic Bool
4744ab47cfaaSmrgSavageDDC1(int scrnIndex)
4745ab47cfaaSmrg{
4746ab47cfaaSmrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
4747ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4748ab47cfaaSmrg    unsigned char byte;
4749ab47cfaaSmrg    xf86MonPtr pMon;
4750ab47cfaaSmrg
4751ab47cfaaSmrg    UnLockExtRegs();
4752ab47cfaaSmrg
4753ab47cfaaSmrg    /* initialize chipset */
4754ab47cfaaSmrg    InI2CREG(byte,psav->I2CPort);
4755ab47cfaaSmrg    OutI2CREG(byte | 0x12,psav->I2CPort);
4756ab47cfaaSmrg
4757ab47cfaaSmrg    pMon = xf86DoEDID_DDC1(scrnIndex,vgaHWddc1SetSpeedWeak(),SavageDDC1Read);
4758ab47cfaaSmrg    if (!pMon)
4759ab47cfaaSmrg        return FALSE;
4760ab47cfaaSmrg
4761ab47cfaaSmrg    xf86PrintEDID(pMon);
4762ab47cfaaSmrg
47638697ee19Smrg    if (!psav->IgnoreEDID)
47648697ee19Smrg        xf86SetDDCproperties(pScrn,pMon);
4765ab47cfaaSmrg
4766ab47cfaaSmrg    /* undo initialization */
4767ab47cfaaSmrg    OutI2CREG(byte,psav->I2CPort);
4768ab47cfaaSmrg
4769ab47cfaaSmrg    return TRUE;
4770ab47cfaaSmrg}
4771ab47cfaaSmrg
4772ab47cfaaSmrgstatic void
4773ab47cfaaSmrgSavageGetTvMaxSize(SavagePtr psav)
4774ab47cfaaSmrg{
4775ab47cfaaSmrg    if( psav->PAL ) {
4776ab47cfaaSmrg	psav->TVSizeX = 800;
4777ab47cfaaSmrg	psav->TVSizeY = 600;
4778ab47cfaaSmrg    }
4779ab47cfaaSmrg    else {
4780ab47cfaaSmrg	psav->TVSizeX = 640;
4781ab47cfaaSmrg	psav->TVSizeY = 480;
4782ab47cfaaSmrg    }
4783ab47cfaaSmrg}
4784ab47cfaaSmrg
4785ab47cfaaSmrg
4786ab47cfaaSmrgstatic Bool
47878697ee19SmrgSavagePanningCheck(ScrnInfoPtr pScrn, DisplayModePtr pMode)
4788ab47cfaaSmrg{
4789ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4790ab47cfaaSmrg    psav->iResX = pMode->CrtcHDisplay;
4791ab47cfaaSmrg    psav->iResY = pMode->CrtcVDisplay;
4792ab47cfaaSmrg
4793ab47cfaaSmrg    if ((psav->iResX < psav->PanelX || psav->iResY < psav->PanelY))
4794ab47cfaaSmrg        psav->FPExpansion = TRUE;
4795ab47cfaaSmrg    else
4796ab47cfaaSmrg        psav->FPExpansion = FALSE;
4797ab47cfaaSmrg
4798ab47cfaaSmrg    if( psav->iResX < pScrn->virtualX || psav->iResY < pScrn->virtualY )
4799ab47cfaaSmrg	return TRUE;
4800ab47cfaaSmrg    else
4801ab47cfaaSmrg	return FALSE;
4802ab47cfaaSmrg}
4803ab47cfaaSmrg
4804ab47cfaaSmrgstatic void
4805ab47cfaaSmrgSavageResetStreams(ScrnInfoPtr pScrn)
4806ab47cfaaSmrg{
4807ab47cfaaSmrg    SavagePtr psav = SAVPTR(pScrn);
4808ab47cfaaSmrg    unsigned char cr67;
4809ab47cfaaSmrg    unsigned char cr69;
4810ab47cfaaSmrg
4811ab47cfaaSmrg    /* disable streams */
4812ab47cfaaSmrg    switch (psav->Chipset) {
4813ab47cfaaSmrg        case S3_SAVAGE_MX:
4814ab47cfaaSmrg        case S3_SUPERSAVAGE:
4815ab47cfaaSmrg            OUTREG32(PRI_STREAM_STRIDE,0);
4816ab47cfaaSmrg            OUTREG32(PRI_STREAM2_STRIDE, 0);
4817ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000);
4818ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000);
4819ab47cfaaSmrg            OUTREG32(PRI_STREAM2_FBUF_ADDR0,0x00000000);
4820ab47cfaaSmrg            OUTREG32(PRI_STREAM2_FBUF_ADDR1,0x00000000);
4821ab47cfaaSmrg	    OUTREG8(CRT_ADDRESS_REG, 0x67);
4822ab47cfaaSmrg            cr67 = INREG8(CRT_DATA_REG);
4823ab47cfaaSmrg	    cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */
4824ab47cfaaSmrg	    cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */
4825ab47cfaaSmrg	    cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */
4826ab47cfaaSmrg            OUTREG8(CRT_DATA_REG, cr67);
4827ab47cfaaSmrg            break;
4828ab47cfaaSmrg	case S3_SAVAGE3D:
4829ab47cfaaSmrg        case S3_SAVAGE4:
4830ab47cfaaSmrg        case S3_TWISTER:
4831ab47cfaaSmrg        case S3_PROSAVAGE:
4832ab47cfaaSmrg        case S3_PROSAVAGEDDR:
4833ab47cfaaSmrg            OUTREG32(PRI_STREAM_STRIDE,0);
4834ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR0,0);
4835ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR1,0);
4836ab47cfaaSmrg	    OUTREG8(CRT_ADDRESS_REG, 0x67);
4837ab47cfaaSmrg            cr67 = INREG8(CRT_DATA_REG);
4838ab47cfaaSmrg	    cr67 &= ~0x0c; /* CR67[2] = 1 : enable stream 1 */
4839ab47cfaaSmrg            OUTREG8(CRT_DATA_REG, cr67);
4840ab47cfaaSmrg	    OUTREG8(CRT_ADDRESS_REG, 0x69);
4841ab47cfaaSmrg            cr69 = INREG8(CRT_DATA_REG);
4842ab47cfaaSmrg	    cr69 &= ~0x80; /* CR69[0] = 1 : Mem-mapped regs */
4843ab47cfaaSmrg            OUTREG8(CRT_DATA_REG, cr69);
4844ab47cfaaSmrg            break;
4845ab47cfaaSmrg        case S3_SAVAGE2000:
4846ab47cfaaSmrg            OUTREG32(PRI_STREAM_STRIDE,0);
4847ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR0,0x00000000);
4848ab47cfaaSmrg            OUTREG32(PRI_STREAM_FBUF_ADDR1,0x00000000);
4849ab47cfaaSmrg	    OUTREG8(CRT_ADDRESS_REG, 0x67);
4850ab47cfaaSmrg            cr67 = INREG8(CRT_DATA_REG);
4851ab47cfaaSmrg	    cr67 &= ~0x08; /* CR67[3] = 1 : Mem-mapped regs */
4852ab47cfaaSmrg	    cr67 &= ~0x04; /* CR67[2] = 1 : enable stream 1 */
4853ab47cfaaSmrg	    cr67 &= ~0x02; /* CR67[1] = 1 : enable stream 2 */
4854ab47cfaaSmrg            OUTREG8(CRT_DATA_REG, cr67);
4855ab47cfaaSmrg            break;
4856ab47cfaaSmrg        default:
4857ab47cfaaSmrg            break;
4858ab47cfaaSmrg    }
4859ab47cfaaSmrg
4860ab47cfaaSmrg}
4861