s3_driver.c revision 92307113
1/*
2 *	Copyright 2001	Ani Joshi <ajoshi@unixbox.com>
3 *
4 *	XFree86 4.x driver for S3 chipsets
5 *
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that copyright
10 * notice and this permission notice appear in supporting documentation and
11 * that the name of Ani Joshi not be used in advertising or
12 * publicity pertaining to distribution of the software without specific,
13 * written prior permission.  Ani Joshi makes no representations
14 * about the suitability of this software for any purpose.  It is provided
15 * "as-is" without express or implied warranty.
16 *
17 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 *
26 *	Credits:
27 *		Thomas Roell <roell@informatik.tu-muenchen.de>
28 *		Mark Vojkovich <markv@valinux.com>
29 *		Kevin E. Martin <martin@valinux.com>
30 *		   - and others for their work on the 3.x S3 driver
31 *
32 *		Dominik Behr
33 *		   - for various hardware donations
34 *
35 *
36 */
37
38#ifdef HAVE_CONFIG_H
39#include "config.h"
40#endif
41
42#include "xf86.h"
43#include "xf86_OSproc.h"
44#include "xf86Pci.h"
45#include "xf86PciInfo.h"
46#include "xf86fbman.h"
47#include "xf86cmap.h"
48#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
49#include "xf86Resources.h"
50#include "xf86RAC.h"
51#endif
52#include "compiler.h"
53#include "xaa.h"
54#include "mipointer.h"
55#include "micmap.h"
56#include "mibstore.h"
57#include "fb.h"
58#include "inputstr.h"
59#include "shadowfb.h"
60#include "IBM.h"
61#include "TI.h"
62
63#include "s3.h"
64#include "s3_reg.h"
65
66#define TRIO64_RAMDAC	0x8811
67
68
69short s3alu[16] =
70{
71	MIX_0,
72	MIX_AND,
73	MIX_SRC_AND_NOT_DST,
74	MIX_SRC,
75	MIX_NOT_SRC_AND_DST,
76	MIX_DST,
77	MIX_XOR,
78	MIX_OR,
79	MIX_NOR,
80	MIX_XNOR,
81	MIX_NOT_DST,
82	MIX_SRC_OR_NOT_DST,
83	MIX_NOT_SRC,
84	MIX_NOT_SRC_OR_DST,
85	MIX_NAND,
86	MIX_1,
87};
88
89
90/*
91 * Prototypes
92 */
93static const OptionInfoRec * S3AvailableOptions(int chipid, int busid);
94static void S3Identify(int flags);
95static Bool S3Probe(DriverPtr drv, int flags);
96static Bool S3PreInit(ScrnInfoPtr pScrn, int flags);
97static Bool S3EnterVT(int scrnIndex, int flags);
98static void S3LeaveVT(int scrnIndex, int flags);
99static void S3Save(ScrnInfoPtr pScrn);
100static Bool S3ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
101			 char **argv);
102static Bool S3MapMem(ScrnInfoPtr pScrn);
103static void S3UnmapMem(ScrnInfoPtr pScrn);
104static Bool S3ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
105static void S3AdjustFrame(int scrnIndex, int x, int y, int flags);
106Bool S3CloseScreen(int scrnIndex, ScreenPtr pScreen);
107Bool S3SaveScreen(ScreenPtr pScreen, int mode);
108static void S3FreeScreen(int scrnIndex, int flags);
109static void S3GenericLoadPalette(ScrnInfoPtr pScrn, int numColors,
110                                 int *indicies, LOCO *colors,
111                                 VisualPtr pVisual);
112static void S3Restore(ScrnInfoPtr pScrn);
113void S3BankZero(ScrnInfoPtr pScrn);
114void S3Regdump(ScrnInfoPtr pScrn);
115static void S3DisplayPowerManagementSet(ScrnInfoPtr pScrn,
116					int PowerManagementMode, int flags);
117
118
119
120_X_EXPORT DriverRec S3 =
121{
122	S3_VERSION,
123	DRIVER_NAME,
124	S3Identify,
125	S3Probe,
126	S3AvailableOptions,
127	NULL,
128	0
129};
130
131/* supported chipsets */
132static SymTabRec S3Chipsets[] = {
133	{ PCI_CHIP_964_0,	"964-0"},
134	{ PCI_CHIP_964_1,	"964-1"},
135	{ PCI_CHIP_968,		"968" },
136	{ PCI_CHIP_TRIO, 	"Trio32/64" },
137	{ PCI_CHIP_AURORA64VP,	"Aurora64V+" },
138	{ PCI_CHIP_TRIO64UVP, 		"Trio64UV+" },
139	{ PCI_CHIP_TRIO64V2_DXGX,	"Trio64V2/DX/GX" },
140	{ -1, NULL }
141};
142
143
144static PciChipsets S3PciChipsets[] = {
145	{ PCI_CHIP_964_0,	PCI_CHIP_964_0,		RES_SHARED_VGA },
146	{ PCI_CHIP_964_1,	PCI_CHIP_964_1,		RES_SHARED_VGA },
147	{ PCI_CHIP_968, 	PCI_CHIP_968, 		RES_SHARED_VGA },
148	{ PCI_CHIP_TRIO, 	PCI_CHIP_TRIO, 		RES_SHARED_VGA },
149	{ PCI_CHIP_AURORA64VP,	PCI_CHIP_AURORA64VP, 	RES_SHARED_VGA },
150	{ PCI_CHIP_TRIO64UVP,	PCI_CHIP_TRIO64UVP, 	RES_SHARED_VGA },
151	{ PCI_CHIP_TRIO64V2_DXGX,	PCI_CHIP_TRIO64V2_DXGX, 	RES_SHARED_VGA },
152	{ -1,			-1,	      		RES_UNDEFINED }
153};
154
155typedef enum {
156	OPTION_NOACCEL,
157	OPTION_HWCURS,
158	OPTION_SLOW_DRAM_REFRESH,
159	OPTION_SLOW_DRAM,
160	OPTION_SLOW_EDODRAM,
161	OPTION_SLOW_VRAM,
162	OPTION_XVIDEO,
163	OPTION_SHADOW_FB,
164	OPTION_ROTATE
165} S3Opts;
166
167static OptionInfoRec S3Options[] = {
168	{ OPTION_NOACCEL, "noaccel", OPTV_BOOLEAN, {0}, FALSE },
169	{ OPTION_HWCURS, "hwcursor", OPTV_BOOLEAN, {0}, FALSE },
170	{ OPTION_SLOW_DRAM_REFRESH, "slow_dram_refresh", OPTV_BOOLEAN, {0}, FALSE },
171	{ OPTION_SLOW_DRAM, "slow_dram", OPTV_BOOLEAN, {0}, FALSE },
172	{ OPTION_SLOW_EDODRAM, "slow_edodram", OPTV_BOOLEAN, {0}, FALSE },
173	{ OPTION_SLOW_VRAM, "slow_vram", OPTV_BOOLEAN, {0}, FALSE },
174	{ OPTION_XVIDEO, "XVideo", OPTV_BOOLEAN, {0}, FALSE },
175	{ OPTION_SHADOW_FB, "ShadowFB", OPTV_BOOLEAN, {0}, FALSE },
176	{ OPTION_ROTATE, "Rotate", OPTV_ANYSTR, {0}, FALSE },
177	{ -1, NULL, OPTV_NONE, {0}, FALSE }
178};
179
180RamDacSupportedInfoRec S3IBMRamdacs[] = {
181	{ IBM524_RAMDAC },
182	{ IBM524A_RAMDAC },
183	{ IBM526_RAMDAC },
184	{ IBM526DB_RAMDAC },
185	{ -1 }
186};
187
188static int s3AccelLinePitches[] = { 640, 800, 1024, 1280, 1600 };
189
190#ifdef XFree86LOADER
191
192MODULESETUPPROTO(S3Setup);
193
194static XF86ModuleVersionInfo S3VersRec = {
195        "s3",
196        MODULEVENDORSTRING,
197        MODINFOSTRING1,
198        MODINFOSTRING2,
199        XORG_VERSION_CURRENT,
200        VERSION_MAJOR, VERSION_MINOR, PATCHLEVEL,
201        ABI_CLASS_VIDEODRV,
202        ABI_VIDEODRV_VERSION,
203        MOD_CLASS_VIDEODRV,
204        {0, 0, 0, 0}
205};
206
207
208_X_EXPORT XF86ModuleData s3ModuleData = { &S3VersRec, S3Setup, NULL };
209
210pointer S3Setup (pointer module, pointer opts, int *errmaj, int *errmin)
211{
212	static Bool setupDone = FALSE;
213
214        if (!setupDone) {
215                setupDone = TRUE;
216                xf86AddDriver(&S3, module, 0);
217                return (pointer) 1;
218        } else {
219                if (errmaj)
220                        *errmaj = LDR_ONCEONLY;
221                return NULL;
222        }
223}
224
225#endif /* XFree86LOADER */
226
227
228static Bool S3GetRec(ScrnInfoPtr pScrn)
229{
230        if (pScrn->driverPrivate)
231                return TRUE;
232
233        pScrn->driverPrivate = xnfcalloc(sizeof(S3Rec), 1);
234
235        return TRUE;
236}
237
238static void S3FreeRec(ScrnInfoPtr pScrn)
239{
240        if (!pScrn->driverPrivate)
241                return;
242
243        xfree(pScrn->driverPrivate);
244        pScrn->driverPrivate = NULL;
245}
246
247static const OptionInfoRec * S3AvailableOptions(int chipid, int busid)
248{
249        return S3Options;
250}
251
252static void S3Identify(int flags)
253{
254        xf86PrintChipsets("S3", "driver (version " DRIVER_VERSION " for S3 chipset",
255                          S3Chipsets);
256}
257
258static Bool S3Probe(DriverPtr drv, int flags)
259{
260	GDevPtr *devSections;
261	int i, *usedChips, numDevSections, numUsed;
262	Bool foundScreen = FALSE;
263
264	/* sanity check */
265	if ((numDevSections = xf86MatchDevice("s3", &devSections)) <= 0)
266                return FALSE;
267
268	/* XXX do ISA later...  some day in the distant future... */
269	numUsed = xf86MatchPciInstances("s3", PCI_VENDOR_S3,
270					S3Chipsets, S3PciChipsets,
271					devSections, numDevSections,
272					drv, &usedChips);
273
274	xfree(devSections);
275
276	if (numUsed <= 0)
277		return FALSE;
278
279	if (flags & PROBE_DETECT)
280		foundScreen = TRUE;
281	else for (i=0; i<numUsed; i++) {
282		ScrnInfoPtr pScrn = NULL;
283                pScrn = xf86ConfigPciEntity(pScrn, 0, usedChips[i], S3PciChipsets,
284                                          NULL, NULL, NULL, NULL, NULL);
285
286		pScrn->driverVersion = VERSION_MAJOR;
287		pScrn->driverName = DRIVER_NAME;
288                pScrn->name = "s3";
289                pScrn->Probe = S3Probe;
290                pScrn->PreInit = S3PreInit;
291                pScrn->ScreenInit = S3ScreenInit;
292                pScrn->SwitchMode = S3SwitchMode;
293                pScrn->AdjustFrame = S3AdjustFrame;
294                pScrn->EnterVT = S3EnterVT;
295                pScrn->LeaveVT = S3LeaveVT;
296		pScrn->FreeScreen = S3FreeScreen;
297
298		foundScreen = TRUE;
299        }
300
301        xfree(usedChips);
302
303        return foundScreen;
304}
305
306static Bool S3PreInit(ScrnInfoPtr pScrn, int flags)
307{
308	EntityInfoPtr pEnt;
309	S3Ptr pS3;
310	vgaHWPtr hwp;
311	ClockRangePtr clockRanges;
312	rgb zeros = {0, 0, 0};
313	Gamma gzeros = {0.0, 0.0, 0.0};
314	int i, vgaCRIndex, vgaCRReg;
315	unsigned char tmp;
316	char *s;
317
318        if (flags & PROBE_DETECT)
319                return FALSE;
320
321        if (!xf86LoadSubModule(pScrn, "vgahw"))
322                return FALSE;
323
324        if (!vgaHWGetHWRec(pScrn))
325                return FALSE;
326
327        hwp = VGAHWPTR(pScrn);
328        vgaHWGetIOBase(hwp);
329
330        pScrn->monitor = pScrn->confScreen->monitor;
331
332        if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb))
333	    return FALSE;
334
335        switch (pScrn->depth) {
336	case 8:
337	case 15:
338	case 16:
339	case 24:
340		/* OK */
341		break;
342	default:
343		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
344			   "Given depth (%d) is not  supported by this driver\n",
345			   pScrn->depth);
346		return FALSE;
347        }
348
349        xf86PrintDepthBpp(pScrn);
350
351        if (pScrn->depth > 8) {
352                if (!xf86SetWeight(pScrn, zeros, zeros))
353                        return FALSE;
354        }
355
356        if (!xf86SetDefaultVisual(pScrn, -1))
357                return FALSE;
358
359        pScrn->progClock = TRUE;
360
361        if (!S3GetRec(pScrn))
362                return FALSE;
363
364	pS3 = S3PTR(pScrn);
365
366	pS3->s3Bpp = (pScrn->bitsPerPixel >> 3);
367
368        xf86CollectOptions(pScrn, NULL);
369        xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, S3Options);
370
371	pS3->XVideo = xf86ReturnOptValBool(S3Options, OPTION_XVIDEO, TRUE);
372	pS3->NoAccel = xf86ReturnOptValBool(S3Options, OPTION_NOACCEL, FALSE);
373	pS3->HWCursor = xf86ReturnOptValBool(S3Options, OPTION_HWCURS, FALSE);
374	pS3->SlowDRAMRefresh = xf86ReturnOptValBool(S3Options, OPTION_SLOW_DRAM_REFRESH, FALSE);
375	pS3->SlowDRAM = xf86ReturnOptValBool(S3Options, OPTION_SLOW_DRAM, FALSE);
376	pS3->SlowEDODRAM = xf86ReturnOptValBool(S3Options, OPTION_SLOW_EDODRAM, FALSE);
377	pS3->SlowVRAM = xf86ReturnOptValBool(S3Options, OPTION_SLOW_VRAM, FALSE);
378
379
380
381	if (xf86GetOptValBool(S3Options, OPTION_SHADOW_FB, &pS3->shadowFB))
382		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowFB %s.\n",
383			   pS3->shadowFB ? "enabled" : "disabled");
384
385	pS3->rotate = 0;
386	if ((s = xf86GetOptValString(S3Options, OPTION_ROTATE))) {
387		if(!xf86NameCmp(s, "CW")) {
388			/* accel is disabled below for shadowFB */
389			pS3->shadowFB = TRUE;
390			pS3->rotate = 1;
391			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
392				   "Rotating screen clockwise - acceleration disabled\n");
393		} else if(!xf86NameCmp(s, "CCW")) {
394			pS3->shadowFB = TRUE;
395			pS3->rotate = -1;
396			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
397				   "counter clockwise - acceleration disabled\n");
398		} else {
399			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
400				   "value for Option \"Rotate\"\n", s);
401			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
402				   "Valid options are \"CW\" or \"CCW\"\n");
403		}
404	}
405
406	if(pS3->shadowFB && !pS3->NoAccel) {
407		pS3->NoAccel = TRUE;
408		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
409			   "HW acceleration not supported with \"shadowFB\".\n");
410	}
411
412
413	if (pS3->rotate && pS3->HWCursor) {
414		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
415			   "HW cursor not supported with \"rotate\".\n");
416		pS3->HWCursor = FALSE;
417	}
418
419
420        if (pScrn->numEntities > 1) {
421                S3FreeRec(pScrn);
422                return FALSE;
423        }
424
425        pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
426#ifndef XSERVER_LIBPCIACCESS
427        if (pEnt->resources) {
428                xfree(pEnt);
429                S3FreeRec(pScrn);
430                return FALSE;
431        }
432#endif
433
434	if (xf86LoadSubModule(pScrn, "int10")) {
435		pS3->pInt10 = xf86InitInt10(pEnt->index);
436	}
437
438	if (xf86LoadSubModule(pScrn, "vbe")) {
439		pS3->pVBE = VBEInit(pS3->pInt10, pEnt->index);
440	}
441
442	if (pS3->shadowFB) {
443		if (!xf86LoadSubModule(pScrn, "shadowfb")) {
444			S3FreeRec(pScrn);
445			return FALSE;
446		}
447	}
448
449	if (!xf86SetGamma(pScrn, gzeros))
450		return FALSE;
451
452        pS3->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
453#ifndef XSERVER_LIBPCIACCESS
454	/* don't disable PIO funcs */
455        xf86SetOperatingState(resVgaMemShared, pEnt->index, ResDisableOpr);
456#endif
457        if (pEnt->device->chipset && *pEnt->device->chipset) {
458                pScrn->chipset = pEnt->device->chipset;
459                pS3->Chipset = xf86StringToToken(S3Chipsets, pScrn->chipset);
460        } else if (pEnt->device->chipID >= 0) {
461                pS3->Chipset = pEnt->device->chipID;
462                pScrn->chipset = (char *)xf86TokenToString(S3Chipsets,
463                                                           pS3->Chipset);
464                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
465			   "ChipID override: 0x%04X\n", pS3->Chipset);
466        } else {
467  	        pS3->Chipset = PCI_DEV_DEVICE_ID(pS3->PciInfo);
468                pScrn->chipset = (char *)xf86TokenToString(S3Chipsets,
469                                                           pS3->Chipset);
470        }
471        if (pEnt->device->chipRev >= 0) {
472                pS3->ChipRev = pEnt->device->chipRev;
473                xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
474                           pS3->ChipRev);
475        } else
476	        pS3->ChipRev = PCI_DEV_REVISION(pS3->PciInfo);
477
478        xfree(pEnt);
479
480        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Chipset: \"%s\"\n",
481		   pScrn->chipset);
482
483#ifndef XSERVER_LIBPCIACCESS
484        pS3->PciTag = pciTag(pS3->PciInfo->bus, pS3->PciInfo->device,
485                             pS3->PciInfo->func);
486#endif
487
488	switch (pS3->Chipset) {
489	case PCI_CHIP_964_0:
490	case PCI_CHIP_964_1:
491	case PCI_CHIP_TRIO:
492		if (pS3->ChipRev >= 0x40) { /* S3 Trio64V+ has the New MMIO */
493			pS3->S3NewMMIO = TRUE;
494			break;
495		}
496	case PCI_CHIP_AURORA64VP:		/* ??? */
497		pS3->S3NewMMIO = FALSE;
498		break;
499	case PCI_CHIP_TRIO64V2_DXGX:
500	case PCI_CHIP_TRIO64UVP:
501	case PCI_CHIP_968:
502		pS3->S3NewMMIO = TRUE;
503		break;
504	}
505
506	/* TODO: Streams Processor and Xv for Old MMIO */
507
508	if (((pS3->Chipset == PCI_CHIP_AURORA64VP) ||
509	     (pS3->Chipset == PCI_CHIP_TRIO64UVP) ||
510	     (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) ||
511	     ((pS3->Chipset == PCI_CHIP_TRIO) && (pS3->ChipRev >= 0x40)))
512	    && (pS3->S3NewMMIO))
513        	pS3->hasStreams = TRUE;
514        else
515        	pS3->hasStreams = FALSE;
516
517	pS3->FBAddress = PCI_REGION_BASE(pS3->PciInfo, 0, REGION_MEM);
518	pScrn->memPhysBase = pS3->FBAddress;
519	pScrn->fbOffset = 0;
520
521	if (pS3->S3NewMMIO)
522		pS3->IOAddress = pS3->FBAddress + S3_NEWMMIO_REGBASE;
523
524	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Framebuffer @ 0x%lx\n",
525		   pS3->FBAddress);
526	if (pS3->S3NewMMIO)
527		xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MMIO @ 0x%lx\n",
528			   pS3->IOAddress);
529
530	pS3->PCIRetry = FALSE;		/* not supported yet */
531
532	pS3->vgaCRIndex = vgaCRIndex = hwp->IOBase + 4;
533	pS3->vgaCRReg = vgaCRReg = hwp->IOBase + 5;
534
535	/* unlock sys regs */
536	outb(vgaCRIndex, 0x38);
537	outb(vgaCRReg, 0x48);
538	outb(vgaCRIndex, 0x39);
539	outb(vgaCRReg, 0xa5);
540
541	outb(vgaCRIndex, 0x40);
542	tmp = inb(vgaCRReg) | 0x01;
543	outb(vgaCRReg, tmp);
544	outb(vgaCRIndex, 0x35);
545	tmp = inb(vgaCRReg) & ~0x30;
546	outb(vgaCRReg, tmp);
547
548	outb(0x3c4, 0x08);
549	outb(0x3c5, 0x06);
550	outb(vgaCRIndex, 0x33);
551	tmp = (inb(vgaCRReg) & ~(0x2 | 0x10 | 0x40)) | 0x20;
552	outb(vgaCRReg, tmp);
553
554	/* unprotect CRTC[0-7] */
555	outb(vgaCRIndex, 0x11);
556	tmp = inb(vgaCRReg) & 0x7f;
557	outb(vgaCRReg, tmp);
558
559	/* wake up */
560	outb(0x46e8, 0x10);
561	outb(0x102, 0x01);
562	outb(0x46e8, 0x08);
563
564	if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX)
565	{
566          /* disable DAC power saving to avoid bright left edge */
567	  outb (0x3d4, 0x86);
568	  outb (0x3d5, 0x80);
569	  /* disable the stream display fetch length control */
570	  outb (0x3d4, 0x90);
571	  outb (0x3d5, 0x00);
572	}
573
574	if (!pScrn->videoRam) {
575		/* probe videoram */
576		outb(vgaCRIndex, 0x36);
577		tmp = inb(vgaCRReg);
578
579		switch ((tmp & 0xe0) >> 5) {
580		case 0:
581			pScrn->videoRam = 4096;
582			break;
583		case 2:
584			pScrn->videoRam = 3072;
585			break;
586		case 3:
587			pScrn->videoRam = 8192;
588			break;
589		case 4:
590			pScrn->videoRam = 2048;
591			break;
592		case 5:
593			pScrn->videoRam = 6144;
594			break;
595		case 6:
596			pScrn->videoRam = 1024;
597			break;
598		}
599		xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
600			   "videoRam = %d Kb\n", pScrn->videoRam);
601	} else {
602		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
603			   "videoRam = %d Kb\n", pScrn->videoRam);
604	}
605
606	if (!xf86LoadSubModule(pScrn, "ramdac"))
607		return FALSE;
608
609	pScrn->rgbBits = 8;	/* set default */
610
611	/* probe for dac */
612	if (S3TiDACProbe(pScrn)) {
613		pS3->DacPreInit = S3TiDAC_PreInit;
614		pS3->DacInit = S3TiDAC_Init;
615		pS3->DacSave = S3TiDAC_Save;
616		pS3->DacRestore = S3TiDAC_Restore;
617#if 0
618		/* FIXME, cursor is drawn in wrong position */
619		pS3->CursorInit = S3Ti_CursorInit;
620#endif
621		pS3->MaxClock = 135000;
622		pScrn->rgbBits = 8;
623		if (pScrn->bitsPerPixel > 8)
624			pS3->LoadPalette = S3TiLoadPalette;
625		else
626			pS3->LoadPalette = S3GenericLoadPalette;
627	}
628	if (S3ProbeIBMramdac(pScrn)) {
629		pS3->DacPreInit = S3IBMRGB_PreInit;
630		pS3->DacInit = S3IBMRGB_Init;
631		pS3->DacSave = S3IBMRGB_Save;
632		pS3->DacRestore = S3IBMRGB_Restore;
633		pS3->CursorInit = S3IBMRGB_CursorInit;
634		pS3->RamDac->SetBpp = IBMramdac526SetBppWeak();
635		pS3->MaxClock = 170000;
636		pScrn->rgbBits = 8;
637		pS3->LoadPalette = S3GenericLoadPalette;
638	}
639	if (S3Trio64DACProbe(pScrn)) {
640		pS3->DacPreInit = S3Trio64DAC_PreInit;
641		pS3->DacInit = S3Trio64DAC_Init;
642		pS3->DacSave = S3Trio64DAC_Save;
643		pS3->DacRestore = S3Trio64DAC_Restore;
644#if 0
645		pS3->CursorInit = S3_CursorInit;	/* FIXME broken */
646#endif
647		switch(pScrn->bitsPerPixel) {
648		case 8:
649			if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX)
650				pS3->MaxClock = 170000;
651			else
652				pS3->MaxClock = 135000;
653
654			pScrn->rgbBits = 6;
655			break;
656		case 16:
657			pS3->MaxClock = 80000;
658			pScrn->rgbBits = 6;
659			break;
660		case 24:
661		case 32:
662			if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX)
663				pS3->MaxClock = 56700;
664			else
665				pS3->MaxClock = 50000;
666
667			pScrn->rgbBits = 8;
668			break;
669		}
670
671		pS3->LoadPalette = S3GenericLoadPalette;
672	}
673
674	if (pS3->RamDac == NULL) {
675		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
676			   "Ramdac probe failed\n");
677		return FALSE;
678	}
679
680	if (!pS3->HWCursor)
681		pS3->CursorInit = NULL;
682
683	pS3->RefClock = S3GetRefClock(pScrn);
684
685	if (pS3->DacPreInit)
686		pS3->DacPreInit(pScrn);
687
688	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RefClock: %d\n",
689		   pS3->RefClock);
690	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Max pixel clock at this depth is %d Mhz\n",
691		   pS3->MaxClock / 1000);
692
693	clockRanges = xnfcalloc(sizeof(ClockRange), 1);
694	clockRanges->next = NULL;
695	clockRanges->minClock = 15600;
696	clockRanges->maxClock = pS3->MaxClock;
697	clockRanges->clockIndex = -1;
698	clockRanges->interlaceAllowed = TRUE;	/* not yet */
699	clockRanges->doubleScanAllowed = TRUE;	/* not yet */
700
701        i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
702                              pScrn->display->modes, clockRanges,
703                              pS3->NoAccel ? NULL : s3AccelLinePitches,
704			      256, 2048,
705			      pScrn->bitsPerPixel, 128, 2048,
706			      pScrn->display->virtualX,
707			      pScrn->display->virtualY, pScrn->videoRam * 1024,
708                              LOOKUP_BEST_REFRESH);
709
710        if (i == -1) {
711                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes left\n");
712                S3FreeRec(pScrn);
713                return FALSE;
714        }
715
716        xf86PruneDriverModes(pScrn);
717
718        if (i == 0 || pScrn->modes == NULL) {
719                xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "no valid modes found\n");
720                S3FreeRec(pScrn);
721                return FALSE;
722        }
723
724        xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
725        pScrn->currentMode = pScrn->modes;
726        xf86PrintModes(pScrn);
727        xf86SetDpi(pScrn, 0, 0);
728
729        xf86LoadSubModule(pScrn, "fb");
730
731	if (!xf86LoadSubModule(pScrn, "xaa"))
732		return FALSE;
733
734	return TRUE;
735}
736
737
738static Bool S3ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
739			 char **argv)
740{
741	ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
742	S3Ptr pS3 = S3PTR(pScrn);
743	BoxRec ScreenArea;
744	int width, height, displayWidth;
745
746	if (pS3->rotate) {
747		height = pScrn->virtualX;
748		width = pScrn->virtualY;
749	} else {
750		width = pScrn->virtualX;
751		height = pScrn->virtualY;
752	}
753
754
755	pScrn->fbOffset = 0;
756
757	if (!S3MapMem(pScrn)) {
758		S3FreeRec(pScrn);
759		return FALSE;
760	}
761
762	S3Save(pScrn);
763
764	vgaHWBlankScreen(pScrn, TRUE);
765
766	if (!S3ModeInit(pScrn, pScrn->currentMode))
767		return FALSE;
768#if 0
769	S3Regdump(pScrn);
770#endif
771	pScrn->vtSema = TRUE;
772
773	S3SaveScreen(pScreen, SCREEN_SAVER_ON);
774
775        miClearVisualTypes();
776        if (pScrn->bitsPerPixel > 8) {
777                if (!miSetVisualTypes(pScrn->depth, TrueColorMask,
778                                      pScrn->rgbBits, pScrn->defaultVisual))
779                        return FALSE;
780        } else {
781                if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
782                                      pScrn->rgbBits, pScrn->defaultVisual))
783                        return FALSE;
784        }
785
786        miSetPixmapDepths ();
787
788        /* no screen rotation assumed */
789        if(pS3->shadowFB) {
790        	pS3->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
791        	pS3->ShadowPtr = xalloc(pS3->ShadowPitch * height);
792		displayWidth = pS3->ShadowPitch / (pScrn->bitsPerPixel >> 3);
793        } else {
794        	pS3->ShadowPtr = NULL;
795		displayWidth = pScrn->displayWidth;
796        }
797
798        if (!fbScreenInit(pScreen, (pS3->shadowFB ? pS3->ShadowPtr : pS3->FBBase),
799			  pScrn->virtualX,
800                          pScrn->virtualY, pScrn->xDpi, pScrn->yDpi,
801                          pScrn->displayWidth, pScrn->bitsPerPixel))
802                return FALSE;
803
804        xf86SetBlackWhitePixels(pScreen);
805
806        if (pScrn->bitsPerPixel > 8) {
807                VisualPtr pVis;
808
809                pVis = pScreen->visuals + pScreen->numVisuals;
810                while (--pVis >= pScreen->visuals) {
811                        if ((pVis->class | DynamicClass) == DirectColor) {
812                                pVis->offsetRed = pScrn->offset.red;
813                                pVis->offsetGreen = pScrn->offset.green;
814                                pVis->offsetBlue = pScrn->offset.blue;
815                                pVis->redMask = pScrn->mask.red;
816                                pVis->greenMask = pScrn->mask.green;
817                                pVis->blueMask = pScrn->mask.blue;
818                        }
819                }
820        }
821	fbPictureInit (pScreen, 0, 0);
822	S3DGAInit(pScreen);
823
824        miInitializeBackingStore(pScreen);
825        xf86SetBackingStore(pScreen);
826
827	/* framebuffer manager setup */
828	ScreenArea.x1 = 0;
829	ScreenArea.y1 = 0;
830	ScreenArea.x2 = pScrn->displayWidth;
831	ScreenArea.y2 = (pScrn->videoRam * 1024) / pS3->s3BppDisplayWidth;
832
833	if (!xf86InitFBManager(pScreen, &ScreenArea)) {
834		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
835			   "Memory manager initialization to (%d,%d) (%d,%d) failed\n",
836			   ScreenArea.x1, ScreenArea.y1,
837			   ScreenArea.x2, ScreenArea.y2);
838		return FALSE;
839	} else
840		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
841			   "Memory manager initialized to (%d,%d) (%d,%d)\n",
842			   ScreenArea.x1, ScreenArea.y1,
843			   ScreenArea.x2, ScreenArea.y2);
844
845	/* 2D acceleration setup */
846
847	if (pS3->NoAccel)
848		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
849			   "Acceleration disabled (by option)\n");
850
851	/* It seems that acceleration isn't supported for 24-bit packed
852	   colour. So disable it. Using shadowFB is recommended in this mode. */
853	if (!pS3->NoAccel && (pScrn->bitsPerPixel == 24)) {
854		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "HW acceleration isn't supported for 24 bpp. Disabled.\n");
855		pS3->NoAccel = TRUE;
856	}
857
858
859	if (!pS3->NoAccel) {
860		if (pS3->S3NewMMIO)
861			if (S3AccelInitNewMMIO(pScreen)) {
862				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
863					   "Acceleration enabled\n");
864				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
865					   "Using NewMMIO\n");
866			} else {
867				xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
868					   "Acceleration initialization failed\n");
869				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
870					   "Acceleration disabled\n");
871			}
872		else {
873			if (S3AccelInitPIO(pScreen)) {
874				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
875					   "Acceleration enabled\n");
876				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
877					   "Using PIO\n");
878			} else {
879				xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
880					   "Acceleration initialization failed\n");
881				xf86DrvMsg(pScrn->scrnIndex, X_INFO,
882					   "Acceleration disabled\n");
883			}
884		}
885	}
886
887        miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
888
889	/* HW cursor setup */
890
891	if (pS3->CursorInit) {
892		if (pS3->CursorInit(pScreen))
893			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using HW cursor\n");
894		else {
895			xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "HW cursor initialization failed\n");
896			xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using SW cursor\n");
897		}
898	} else
899		xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using SW cursor\n");
900
901
902	/* Shadow framebuffer setup */
903
904	if (pS3->shadowFB) {
905		RefreshAreaFuncPtr refreshArea = S3RefreshArea;
906
907		if (pS3->rotate) {
908			if (!pS3->PointerMoved) {
909				pS3->PointerMoved = pScrn->PointerMoved;
910				pScrn->PointerMoved = S3PointerMoved;
911			}
912
913			switch (pScrn->bitsPerPixel) {
914			case 8: refreshArea = S3RefreshArea8; break;
915			case 16: refreshArea = S3RefreshArea16; break;
916			case 24: refreshArea = S3RefreshArea24; break;
917			case 32: refreshArea = S3RefreshArea32; break;
918			}
919		}
920
921		ShadowFBInit(pScreen, refreshArea);
922	}
923
924
925
926        if (!miCreateDefColormap(pScreen))
927                return FALSE;
928
929        if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,
930				 pS3->LoadPalette, NULL,
931                                 CMAP_RELOAD_ON_MODE_SWITCH))
932                return FALSE;
933
934	vgaHWBlankScreen(pScrn, FALSE);
935
936        pScreen->SaveScreen = S3SaveScreen;
937        pS3->CloseScreen = pScreen->CloseScreen;
938        pScreen->CloseScreen = S3CloseScreen;
939
940	xf86DPMSInit(pScreen, S3DisplayPowerManagementSet, 0);
941
942#ifndef XSERVER_LIBPCIACCESS
943	/* XXX Check if I/O and Mem flags need to be the same. */
944	pScrn->racIoFlags = pScrn->racMemFlags = RAC_COLORMAP
945	    | RAC_FB | RAC_VIEWPORT | RAC_CURSOR;
946#endif
947
948	if (pS3->SlowEDODRAM)
949		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
950			   "SlowEDODRAM: Setting 2-cycle EDO\n");
951
952	if (pS3->SlowVRAM)
953		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
954			   "SlowVRAM: -RAS low time is 4.5 MCLKs\n");
955
956	if (pS3->SlowDRAM)
957		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
958			   "SlowDRAM: -RAS precharge time is 3.5 MCLKs\n");
959
960	if (pS3->SlowDRAMRefresh)
961		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
962			   "SlowDRAMRefresh: three refresh cycles per scanline\n");
963
964	/* XVideo setup */
965
966	if (pS3->XVideo) {
967		if (!pS3->hasStreams) {
968			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overlay video isn't supported by video hardware. Disabled.\n");
969			pS3->XVideo = FALSE;
970		} else if (pScrn->bitsPerPixel < 16) {
971			xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Overlay video isn't supported for %d bpp. Disabled.\n", pScrn->bitsPerPixel);
972			pS3->XVideo = FALSE;
973		}
974	} else
975		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
976			   "Overlay video disabled by option\n");
977
978	/* At present time we support XV only for chips with New MMIO */
979	if ((pS3->XVideo) && (pS3->S3NewMMIO))
980		S3InitVideo(pScreen);
981
982	switch (pScrn->bitsPerPixel) {
983	case 8:
984		pS3->Streams_FIFO = FIFO_PS16_SS8;
985		break;
986	case 15:
987	case 16:
988		pS3->Streams_FIFO = FIFO_PS12_SS12;
989		break;
990	case 24:
991	case 32:
992		pS3->Streams_FIFO = FIFO_PS8_SS16;
993		break;
994	}
995
996        return TRUE;
997}
998
999
1000
1001
1002static void S3Save(ScrnInfoPtr pScrn)
1003{
1004	S3Ptr pS3 = S3PTR(pScrn);
1005	S3RegPtr save = &pS3->SavedRegs;
1006	vgaHWPtr hwp = VGAHWPTR(pScrn);
1007        vgaRegPtr pVga = &hwp->SavedReg;
1008	int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
1009	int i;
1010	unsigned char cr5c = 0;
1011
1012	S3BankZero(pScrn);
1013
1014	save->clock = inb(0x3cc);
1015
1016	vgaHWSave(pScrn, pVga, VGA_SR_ALL);
1017
1018	if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
1019		outb(vgaCRIndex, 0x5c);
1020		cr5c = inb(vgaCRReg);
1021	}
1022
1023	pS3->DacSave(pScrn);
1024
1025	for(i=0; i<5; i++) {
1026		outb(vgaCRIndex, 0x30 + i);
1027		save->s3save[i] = inb(vgaCRReg);
1028		outb(vgaCRIndex, 0x38 + i);
1029		save->s3save[5 + i] = inb(vgaCRReg);
1030	}
1031
1032	for (i=0; i<16; i++) {
1033		outb(vgaCRIndex, 0x40 + i);
1034		save->s3syssave[i] = inb(vgaCRReg);
1035	}
1036
1037	outb(vgaCRIndex, 0x45);
1038	inb(vgaCRReg);
1039	outb(vgaCRIndex, 0x4a);
1040	for(i=0; i<4; i++) {
1041		save->color_stack[i] = inb(vgaCRReg);
1042		outb(vgaCRReg, save->color_stack[i]);
1043	}
1044
1045	outb(vgaCRIndex, 0x45);
1046	inb(vgaCRReg);
1047	outb(vgaCRIndex, 0x4b);
1048	for(i=4; i<8; i++) {
1049		save->color_stack[i] = inb(vgaCRReg);
1050		outb(vgaCRReg, save->color_stack[i]);
1051	}
1052
1053	for(i=0; i<16; i++) {
1054		for (i=0; i<16; i++) {
1055			if (!((1 << i) & 0x673b))
1056				continue;
1057			outb(vgaCRIndex, 0x50 + i);
1058			save->s3syssave[i + 16] = inb(vgaCRReg);
1059		}
1060	}
1061
1062	if (pS3->RamDac->RamDacType == TI3025_RAMDAC)
1063		save->s3syssave[0x0c + 16] = cr5c;
1064
1065	for(i=32; i<46; i++) {
1066		outb(vgaCRIndex, 0x40 + i);
1067		save->s3syssave[i] = inb(vgaCRReg);
1068	}
1069}
1070
1071
1072Bool S3SaveScreen(ScreenPtr pScreen, int mode)
1073{
1074	return vgaHWSaveScreen(pScreen, mode);
1075}
1076
1077
1078static void S3FreeScreen(int scrnIndex, int flags)
1079{
1080        ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1081
1082        vgaHWFreeHWRec(pScrn);
1083
1084        S3FreeRec(pScrn);
1085}
1086
1087
1088Bool S3CloseScreen(int scrnIndex, ScreenPtr pScreen)
1089{
1090        ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1091        S3Ptr pS3 = S3PTR(pScrn);
1092        vgaHWPtr hwp = VGAHWPTR(pScrn);
1093
1094        if (pScrn->vtSema) {
1095                vgaHWUnlock(hwp);
1096		S3Restore(pScrn);
1097                vgaHWLock(hwp);
1098                S3UnmapMem(pScrn);
1099        }
1100
1101	if (pS3->DGAModes)
1102		xfree(pS3->DGAModes);
1103	pS3->DGAModes = NULL;
1104
1105        pScrn->vtSema = FALSE;
1106        pScreen->CloseScreen = pS3->CloseScreen;
1107
1108        return (*pScreen->CloseScreen)(scrnIndex, pScreen);
1109}
1110
1111
1112Bool S3SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1113{
1114	return S3ModeInit(xf86Screens[scrnIndex], mode);
1115
1116}
1117
1118
1119static void S3GenericLoadPalette(ScrnInfoPtr pScrn, int numColors,
1120                                 int *indicies, LOCO *colors,
1121                                 VisualPtr pVisual)
1122{
1123        int i, index;
1124
1125        for (i=0; i<numColors; i++) {
1126                index = indicies[i];
1127                outb(0x3c8, index);
1128                outb(0x3c9, colors[index].red);
1129                outb(0x3c9, colors[index].green);
1130                outb(0x3c9, colors[index].blue);
1131        }
1132}
1133
1134
1135static Bool S3MapMem(ScrnInfoPtr pScrn)
1136{
1137	S3Ptr pS3 = S3PTR(pScrn);
1138
1139	if (pS3->S3NewMMIO) {
1140
1141
1142#ifndef XSERVER_LIBPCIACCESS
1143		pS3->MMIOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
1144					      pS3->PciTag, pS3->IOAddress,
1145					      S3_NEWMMIO_REGSIZE);
1146#else
1147		{
1148			void** result = (void**)&pS3->MMIOBase;
1149			int err = pci_device_map_range(pS3->PciInfo,
1150						       pS3->IOAddress,
1151						       S3_NEWMMIO_REGSIZE,
1152						       PCI_DEV_MAP_FLAG_WRITABLE,
1153						       result);
1154
1155			if (err)
1156				return FALSE;
1157		}
1158#endif
1159		if (!pS3->MMIOBase) {
1160			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1161				   "Could not map MMIO\n");
1162			return FALSE;
1163		}
1164	}
1165
1166#ifndef XSERVER_LIBPCIACCESS
1167	pS3->FBBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_FRAMEBUFFER,
1168				    pS3->PciTag, pS3->FBAddress,
1169				    pScrn->videoRam * 1024);
1170
1171#else
1172	{
1173		void** result = (void**)&pS3->FBBase;
1174		int err = pci_device_map_range(pS3->PciInfo,
1175					       pS3->FBAddress,
1176					       pScrn->videoRam * 1024,
1177					       PCI_DEV_MAP_FLAG_WRITABLE |
1178					       PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1179					       result);
1180
1181		if (err)
1182			return FALSE;
1183	}
1184#endif
1185	if (!pS3->FBBase) {
1186		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1187			   "Could not map framebuffer\n");
1188		return FALSE;
1189	}
1190
1191	pS3->FBCursorOffset = pScrn->videoRam - 1;
1192
1193	return TRUE;
1194}
1195
1196
1197static void S3UnmapMem(ScrnInfoPtr pScrn)
1198{
1199	S3Ptr pS3 = S3PTR(pScrn);
1200
1201	if (pS3->S3NewMMIO) {
1202#ifndef XSERVER_LIBPCIACCESS
1203		xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pS3->MMIOBase,
1204				S3_NEWMMIO_REGSIZE);
1205#else
1206		pci_device_unmap_range(pS3->PciInfo, pS3->MMIOBase, S3_NEWMMIO_REGSIZE);
1207#endif
1208	}
1209
1210#ifndef XSERVER_LIBPCIACCESS
1211	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pS3->FBBase,
1212			pScrn->videoRam * 1024);
1213#else
1214	pci_device_unmap_range(pS3->PciInfo, pS3->FBBase, pScrn->videoRam * 1024);
1215#endif
1216
1217	return;
1218}
1219
1220
1221static int S3GetPixMuxShift(ScrnInfoPtr pScrn)
1222{
1223	S3Ptr pS3 = S3PTR(pScrn);
1224	int shift = 0;
1225
1226	if (pS3->Chipset == PCI_CHIP_968)
1227		shift = 1;	/* XXX IBMRGB */
1228	else if (pS3->Chipset == PCI_CHIP_TRIO ||
1229	         pS3->Chipset == PCI_CHIP_TRIO64UVP ||
1230	         pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX) {
1231		if (pS3->s3Bpp == 2)
1232			shift = -1;
1233		else
1234			shift = 0;
1235	}
1236
1237	return shift;
1238}
1239
1240static Bool S3ModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
1241{
1242	S3Ptr pS3 = S3PTR(pScrn);
1243	S3RegPtr new = &pS3->ModeRegs;
1244        vgaHWPtr hwp = VGAHWPTR(pScrn);
1245        vgaRegPtr pVga = &hwp->ModeReg;
1246        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
1247	int vgaIOBase = hwp->IOBase;
1248	int r, n, m;
1249	unsigned char tmp;
1250
1251	pS3->pixMuxShift = S3GetPixMuxShift(pScrn);
1252
1253	pS3->s3BppDisplayWidth = pScrn->displayWidth * pS3->s3Bpp;
1254	pS3->hwCursor = (mode->Flags & V_DBLSCAN) ? FALSE : TRUE;
1255	pS3->HDisplay = mode->HDisplay;
1256
1257	pS3->s3ScissB = ((pScrn->videoRam * 1024) / pS3->s3BppDisplayWidth) - 1;
1258	pS3->s3ScissR = pScrn->displayWidth - 1;
1259
1260	/*
1261	   Set correct blanking for S3 Trio64V2. It's also needed
1262	   to clear cr33_5.
1263	*/
1264	if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX)
1265		mode->CrtcHBlankStart = mode->CrtcHDisplay + 8;
1266
1267	if ((mode->HTotal == mode->CrtcHTotal) && (pS3->pixMuxShift != 0)) {
1268		if (pS3->pixMuxShift > 0) {
1269			mode->CrtcHTotal >>= pS3->pixMuxShift;
1270			mode->CrtcHDisplay >>= pS3->pixMuxShift;
1271			mode->CrtcHBlankStart >>= pS3->pixMuxShift;
1272			mode->CrtcHBlankEnd >>= pS3->pixMuxShift;
1273			mode->CrtcHSyncStart >>= pS3->pixMuxShift;
1274			mode->CrtcHSyncEnd >>= pS3->pixMuxShift;
1275			mode->CrtcHSkew >>= pS3->pixMuxShift;
1276		} else if (pS3->pixMuxShift < 0) {
1277			mode->CrtcHTotal <<= -pS3->pixMuxShift;
1278			mode->CrtcHDisplay <<= -pS3->pixMuxShift;
1279			mode->CrtcHBlankStart <<= -pS3->pixMuxShift;
1280			mode->CrtcHBlankEnd <<= -pS3->pixMuxShift;
1281			mode->CrtcHSyncStart <<= -pS3->pixMuxShift;
1282			mode->CrtcHSyncEnd <<= -pS3->pixMuxShift;
1283			mode->CrtcHSkew <<= -pS3->pixMuxShift;
1284		}
1285	}
1286
1287        if (!vgaHWInit(pScrn, mode))
1288                return FALSE;
1289
1290
1291
1292	pVga->MiscOutReg |= 0x0c;
1293	pVga->Sequencer[0] = 0x03;
1294	pVga->CRTC[19] = pS3->s3BppDisplayWidth >> 3;
1295	pVga->CRTC[23] = 0xe3;
1296	pVga->Attribute[0x11] = 0xff;
1297
1298	if (vgaIOBase == 0x3b0)
1299		pVga->MiscOutReg &= 0xfe;
1300	else
1301		pVga->MiscOutReg |= 0x01;
1302
1303	/* ok i give up also, i'm writing in here */
1304
1305	vgaHWProtect(pScrn, TRUE);
1306
1307
1308	if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
1309		outb(vgaCRIndex, 0x5c);
1310		tmp = inb(vgaCRReg);
1311		outb(vgaCRReg, tmp & 0xdf);
1312
1313		S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x7f, 0x00);
1314	}
1315
1316	pS3->DacInit(pScrn, mode);
1317
1318	outb(0x3c2, pVga->MiscOutReg);
1319
1320	for(r=1; r<5; r++) {
1321		outw(0x3c4, (pVga->Sequencer[r] << 8) | r);
1322	}
1323
1324	/* We need to set this first - S3 *is* broken */
1325	outw(vgaCRIndex, (pVga->CRTC[17] << 8) | 17);
1326	for(r=0; r<25; r++)
1327		outw(vgaCRIndex, (pVga->CRTC[r] << 8) | r);
1328
1329	for(r=0; r<9; r++)
1330		outw(0x3ce, (pVga->Graphics[r] << 8) | r);
1331
1332	inb(vgaIOBase + 0x0a);
1333
1334	for(r=0; r<16; r++) {
1335		outb(0x3c0, r);
1336		outb(0x3c0, pVga->Attribute[r]);
1337	}
1338	for(r=16; r<21; r++) {
1339		outb(0x3c0, r | 0x20);
1340		outb(0x3c0, pVga->Attribute[r]);
1341	}
1342
1343
1344	new->cr31 = 0x8d;
1345	outb(vgaCRIndex, 0x31);
1346	outb(vgaCRReg, new->cr31);
1347
1348	new->cr32 = 0x00;
1349	outb(vgaCRIndex, 0x32);
1350	outb(vgaCRReg, new->cr32);
1351
1352	outb(vgaCRIndex, 0x33);
1353	new->cr33 = inb(vgaCRReg) | 0x20;
1354	if ((pS3->Chipset == PCI_CHIP_964_0) ||
1355	    (pS3->Chipset == PCI_CHIP_964_1))
1356		new->cr33 = 0x20;
1357	else if (pS3->Chipset == PCI_CHIP_TRIO64V2_DXGX)
1358		new->cr33 &= ~0x20;
1359	outb(vgaCRReg, new->cr33);
1360
1361	new->cr34 = 0x10;
1362	outb(vgaCRIndex, 0x34);
1363	outb(vgaCRReg, new->cr34);
1364
1365	if (pS3->Chipset != PCI_CHIP_AURORA64VP) {
1366		new->cr3b = (pVga->CRTC[0] + pVga->CRTC[4] + 1) / 2;
1367		outb(vgaCRIndex, 0x3b);
1368		outb(vgaCRReg, new->cr3b);
1369	}
1370
1371	new->cr3c = pVga->CRTC[0] / 2;
1372	outb(vgaCRIndex, 0x3c);
1373	outb(vgaCRReg, new->cr3c);
1374
1375	outb(vgaCRIndex, 0x40);
1376	tmp = inb(vgaCRReg);
1377	new->cr40 = (tmp & 0xf2) | 0x05;
1378	outb(vgaCRReg, new->cr40);
1379
1380	outb(vgaCRIndex, 0x43);
1381	switch (pScrn->bitsPerPixel) {
1382	case 24:
1383	case 32:
1384		new->cr43 = inb(vgaCRReg);
1385		break;
1386	case 15:
1387	case 16:
1388		if ((pS3->RamDac->RamDacType == IBM524_RAMDAC) ||
1389		    (pS3->RamDac->RamDacType == IBM524A_RAMDAC) ||
1390		    (pS3->RamDac->RamDacType == TI3025_RAMDAC))
1391			new->cr43 = 0x10;
1392		else if (pS3->RamDac->RamDacType == TRIO64_RAMDAC)
1393			new->cr43 = 0x09;
1394		break;
1395	case 8:
1396	default:
1397		new->cr43 = 0x00;
1398		break;
1399	}
1400	outb(vgaCRReg, new->cr43);
1401
1402	new->cr44 = 0x00;
1403	outb(vgaCRIndex, 0x44);
1404	outb(vgaCRReg, new->cr44);
1405
1406	outb(vgaCRIndex, 0x45);
1407	new->cr45 = inb(vgaCRReg) & 0xf2;
1408	outb(vgaCRReg, new->cr45);
1409
1410	outb(vgaCRIndex, 0x50);
1411	tmp = inb(vgaCRReg) & ~0xf1;
1412	switch (pScrn->bitsPerPixel) {
1413	case 8:
1414		break;
1415	case 16:
1416		tmp |= 0x10;
1417		break;
1418	case 24:
1419		tmp |= 0x20; /* there is no such value in spec s3.txt */
1420		break;
1421	case 32:
1422		tmp |= 0x30;
1423		break;
1424	}
1425
1426	switch (pScrn->displayWidth) {
1427	case 640:
1428		tmp |= 0x40;
1429		break;
1430	case 800:
1431		tmp |= 0x80;
1432		break;
1433	case 1152:
1434		tmp |= 0x01;
1435		break;
1436	case 1280:
1437		tmp |= 0xc0;
1438		break;
1439	case 1600:
1440		tmp |= 0x81;
1441		break;
1442	}
1443	new->cr50 = tmp;
1444	outb(vgaCRReg, new->cr50);
1445
1446
1447	outb(vgaCRIndex, 0x51);
1448	new->cr51 = (inb(vgaCRReg) & 0xc0) |
1449		    ((pS3->s3BppDisplayWidth >> 7) & 0x30);
1450	outb(vgaCRReg, new->cr51);
1451
1452	outb(vgaCRIndex, 0x53);
1453	new->cr53 = inb(vgaCRReg);
1454	if (pS3->S3NewMMIO)
1455		new->cr53 |= 0x18;
1456	else
1457		new->cr53 &= ~0x18;
1458	outb(vgaCRReg, new->cr53);
1459
1460	n = 255;
1461	outb(vgaCRIndex, 0x54);
1462	{
1463		int clock2, mclk;
1464
1465		clock2 = mode->Clock * pS3->s3Bpp;
1466		if (pScrn->videoRam < 2048)
1467			clock2 *= 2;
1468		mclk = pS3->mclk;
1469		m = (int)((mclk/1000.0*.72+16.867)*89.736/(clock2/1000.0+39)-21.1543);
1470		if (pScrn->videoRam < 2048)
1471			m /= 2;
1472		if (m >31)
1473			m = 31;
1474		else if (m < 0) {
1475			m = 0;
1476			n = 16;
1477		}
1478	}
1479	new->cr54 = m << 3;
1480	outb(vgaCRReg, new->cr54);
1481
1482	if (n < 0)
1483		n = 0;
1484	else if (n > 255)
1485		n = 255;
1486	outb(vgaCRIndex, 0x60);
1487	new->cr60 = n;
1488	outb(vgaCRReg, new->cr60);
1489
1490	if (pS3->hasStreams) {
1491		new->cr60 = 255;
1492		outb(vgaCRIndex, 0x60);
1493		outb(vgaCRReg, new->cr60);
1494
1495		new->cr54 = 31 << 3;
1496		outb(vgaCRIndex, 0x54);
1497		outb(vgaCRReg, new->cr54);
1498	}
1499
1500	outb(vgaCRIndex, 0x55);
1501	new->cr55 = (inb(vgaCRReg) & 0x08) | 0x40;
1502	outb(vgaCRReg, new->cr55);
1503
1504	outb(vgaCRIndex, 0x5e);
1505	new->cr5e = (((mode->CrtcVTotal - 2) & 0x400) >> 10)	|
1506		    (((mode->CrtcVDisplay - 1) & 0x400) >> 9)	|
1507		    (((mode->CrtcVSyncStart) & 0x400) >> 8)	|
1508		    (((mode->CrtcVSyncStart) & 0x400) >> 6)	| 0x40;
1509	outb(vgaCRReg, new->cr5e);
1510
1511	{
1512		int i;
1513		unsigned int j;
1514
1515		i = ((((mode->CrtcHTotal >> 3) - 5) & 0x100) >> 8)      |
1516		    ((((mode->CrtcHDisplay >> 3) - 1) & 0x100) >> 7)    |
1517		    ((((mode->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6)  |
1518		    ((mode->CrtcHSyncStart & 0x800) >> 7);
1519		if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 64)
1520			i |= 0x08;
1521		if ((mode->CrtcHSyncEnd >> 3) - (mode->CrtcHSyncStart >> 3) > 32)
1522			i |= 0x20;
1523
1524		outb(vgaCRIndex, 0x3b);
1525		j = ((pVga->CRTC[0] + ((i & 0x01) << 8) +
1526		      pVga->CRTC[4] + ((i & 0x10) << 4) + 1) / 2);
1527
1528            	if (j - (pVga->CRTC[4] + ((i & 0x10) << 4)) < 4) {
1529                	if (pVga->CRTC[4] + ((i & 0x10) << 4) + 4 <= pVga->CRTC[0] + ((i & 0x01) << 8))
1530                    		j = pVga->CRTC[4] + ((i & 0x10) << 4) + 4;
1531                	else
1532                    		j = pVga->CRTC[0] + ((i & 0x01) << 8) + 1;
1533		}
1534		if (pS3->Chipset == PCI_CHIP_AURORA64VP) {
1535			outb(vgaCRReg, 0x00);
1536			i &= ~0x40;
1537		} else {
1538			new->cr3b = j & 0xff;
1539			outb(vgaCRReg, new->cr3b);
1540			i |= (j & 0x100) >> 2;
1541		}
1542
1543		outb(vgaCRIndex, 0x3c);
1544		new->cr3c = (pVga->CRTC[0] + ((i & 0x01) << 8)) / 2;
1545		outb(vgaCRReg, new->cr3c);
1546
1547		outb(vgaCRIndex, 0x5d);
1548		new->cr5d = (inb(vgaCRReg) & 0x80) | i;
1549		outb(vgaCRReg, new->cr5d);
1550	}
1551
1552	{
1553		int i;
1554
1555		if (pScrn->videoRam > 1024)
1556			i = mode->HDisplay * pS3->s3Bpp / 8 + 1;
1557		else
1558			i = mode->HDisplay * pS3->s3Bpp / 4 + 1;
1559
1560		outb(vgaCRIndex, 0x61);
1561		tmp = 0x80 | (inb(vgaCRReg) & 0x60) | (i >> 8);
1562		new->cr61 = tmp;
1563		outb(vgaCRReg, new->cr61);
1564		outb(vgaCRIndex, 0x62);
1565		new->cr62 = i & 0xff;
1566		outb(vgaCRReg, new->cr62);
1567	}
1568
1569	if (mode->Flags & V_INTERLACE) {
1570		outb(vgaCRIndex, 0x42);
1571		new->cr42 = inb(vgaCRReg) | 0x20;
1572		outb(vgaCRReg, new->cr42);
1573	} else {
1574		outb(vgaCRIndex, 0x42);
1575		new->cr42 = inb(vgaCRReg) & ~0x20;
1576		outb(vgaCRReg, new->cr42);
1577	}
1578
1579	if (pS3->hasStreams) {
1580		unsigned char a;
1581
1582		outb(vgaCRIndex, 0x67);
1583		a = inb(vgaCRReg) & 0xfe;
1584
1585		switch (pScrn->depth) {
1586		case 8:
1587			break;
1588		case 15:
1589			a |= (3 << 4);
1590			break;
1591		case 16:
1592			a |= (5 << 4);
1593			break;
1594		case 24:
1595			a |= (13 << 4);
1596			break;
1597		}
1598
1599		if (pS3->hasStreams)
1600			a |= (3 << 2);
1601
1602		WaitVSync(); /* Wait for VSync before setting mode */
1603		outb(vgaCRReg, a);
1604	}
1605
1606	if (pS3->Chipset == PCI_CHIP_968) {
1607		unsigned char a;
1608
1609		outb(vgaCRIndex, 0x67);
1610		a = inb(vgaCRReg) & 0xfe;
1611#if 0
1612		switch (pScrn->depth) {
1613			case 8:
1614				break;
1615			case 15:
1616				a |= (3 << 4);
1617				break;
1618			case 16:
1619				a |= (5 << 4);
1620				a |= (3 << 2);	/* streams */
1621				break;
1622			case 24:
1623				a |= (13 << 4);
1624				a |= (3 << 2);	/* streams */
1625				break;
1626		}
1627#endif
1628		outb(vgaCRReg, a);
1629
1630		outb(vgaCRIndex, 0x6d);
1631		outb(vgaCRReg, 0x00);
1632	}
1633
1634	if ((pS3->Chipset == PCI_CHIP_964_0) ||
1635	    (pS3->Chipset == PCI_CHIP_964_1)) {
1636		unsigned char bdelay;
1637
1638		outb(vgaCRIndex, 0x6d);
1639		bdelay = inb(vgaCRReg);
1640
1641		if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
1642			if (pS3->s3Bpp == 1) {
1643				if (mode->Clock > 80000)
1644					bdelay = 0x02;
1645				else
1646					bdelay = 0x03;
1647			} else if (pS3->s3Bpp == 2) {
1648				if (mode->Clock > 80000)
1649					bdelay = 0x00;
1650				else
1651					bdelay = 0x01;
1652			} else
1653				bdelay = 0x00;
1654		}
1655
1656		outb(vgaCRReg, bdelay);
1657	}
1658
1659	outb(vgaCRIndex, 0x66);
1660	new->cr66 = inb(vgaCRReg);
1661	if (pS3->S3NewMMIO)
1662		new->cr66 |= 0x88;
1663	else
1664		new->cr66 |= 0x80;
1665	outb(vgaCRReg, new->cr66);
1666
1667
1668	if (pS3->SlowDRAMRefresh)
1669		new->cr3a = 0xb7;
1670       	else
1671		new->cr3a = 0xb5;
1672	outb(vgaCRIndex, 0x3a);
1673	outb(vgaCRReg, new->cr3a);
1674
1675	if (pS3->SlowVRAM) {
1676		/*
1677		 * some Diamond Stealth 64 VRAM cards have a problem with
1678		 * VRAM timing, increas -RAS low timing from 3.5 MCLKs
1679		 * to 4.5 MCLKs
1680		 */
1681		outb(vgaCRIndex, 0x39);
1682		outb(vgaCRReg, 0xa5);
1683		outb(vgaCRIndex, 0x68);
1684		tmp = inb(vgaCRReg);
1685		if (tmp & 0x30)				/* 3.5 MCLKs */
1686			outb(vgaCRReg, tmp & 0xef);	/* 4.5 MCLKs */
1687	}
1688
1689	if (pS3->SlowDRAM) {
1690		/*
1691		 * fixes some pixel errors for a SPEA Trio64V+ card
1692		 * increase -RAS precharge timing from 2.5 MCLKs
1693		 * to 3.5 MCLKs
1694		 */
1695		outb(vgaCRIndex, 0x39);
1696		outb(vgaCRReg, 0xa5);
1697		outb(vgaCRIndex, 0x68);
1698		tmp = inb(vgaCRReg) & 0xf7;
1699		outb(vgaCRReg, tmp);			/* 3.5 MCLKs */
1700	}
1701
1702	if (pS3->SlowEDODRAM) {
1703		/*
1704		 * fixes some pixel errors for a SPEA Trio64V+ card
1705		 * increase from 1-cycle to 2-cycle EDO mode
1706		 */
1707		outb(vgaCRIndex, 0x39);
1708
1709		outb(vgaCRReg, 0xa5);
1710		outb(vgaCRIndex, 0x36);
1711		tmp = inb(vgaCRReg);
1712		if (!(tmp & 0x0c))			/* 1-cycle EDO */
1713			outb(vgaCRReg, tmp | 0x08);	/* 2-cycle EDO */
1714	}
1715
1716	if (pS3->Chipset == PCI_CHIP_AURORA64VP) {
1717		outb(0x3c4, 0x08);
1718		outb(0x3c5, 0x06);
1719#if 0
1720		outb(0x3c4, 0x54);
1721		outb(0x3c5, 0x10);
1722		outb(0x3c4, 0x55);
1723		outb(0x3c5, 0x00);
1724		outb(0x3c4, 0x56);
1725		outb(0x3c5, 0x1c);
1726		outb(0x3c4, 0x57);
1727		outb(0x3c5, 0x00);
1728#else
1729		outb(0x3c4, 0x54);
1730		outb(0x3c5, 0x1f);
1731		outb(0x3c4, 0x55);
1732		outb(0x3c5, 0x1f);
1733		outb(0x3c4, 0x56);
1734		outb(0x3c5, 0x1f);
1735		outb(0x3c4, 0x57);
1736		outb(0x3c5, 0x1f);
1737#endif
1738
1739		outb(0x3c4, 0x08);
1740		outb(0x3c5, 0x00);
1741	}
1742
1743	pScrn->AdjustFrame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
1744
1745       	vgaHWProtect(pScrn, FALSE);
1746
1747	if (pScrn->displayWidth == 1024)
1748		outw(ADVFUNC_CNTL, 0x0007);
1749	else
1750		outw(ADVFUNC_CNTL, 0x0003);
1751
1752	outb(0x3c6, 0x00);
1753
1754	outw(SUBSYS_CNTL, 0x8000 | 0x1000);
1755	outw(SUBSYS_CNTL, 0x4000 | 0x1000);
1756
1757	inw(SUBSYS_STAT);
1758
1759	outw(0xbee8, 0x5000 | 0x0004 | 0x000c);
1760
1761	outb(0x3c6, 0xff);
1762
1763	new->cr59 = pS3->FBAddress >> 24;
1764	new->cr5a = pS3->FBAddress >> 16;
1765
1766	if (pScrn->videoRam <= 1024)
1767		new->cr58 = 0x15;
1768	else if (pScrn->videoRam <= 2048)
1769		new->cr58 = 0x16;
1770	else
1771		new->cr58 = 0x17;
1772
1773	if ((pS3->Chipset == PCI_CHIP_968) ||
1774	    (pS3->Chipset == PCI_CHIP_964_0) ||
1775	    (pS3->Chipset == PCI_CHIP_964_1))
1776		new->cr58 |= 0x40;
1777
1778	outb(vgaCRIndex, 0x59);
1779	outb(vgaCRReg, new->cr59);
1780	outb(vgaCRIndex, 0x5a);
1781	outb(vgaCRReg, new->cr5a);
1782	outb(vgaCRIndex, 0x58);
1783	outb(vgaCRReg, new->cr58);
1784
1785	WaitQueue(5);
1786	SET_SCISSORS(0, 0, pS3->s3ScissR, pS3->s3ScissB);
1787
1788	if (pS3->hasStreams)
1789		S3InitStreams(pScrn, mode);
1790
1791	return TRUE;
1792}
1793
1794
1795static Bool S3EnterVT(int scrnIndex, int flags)
1796{
1797        ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1798        vgaHWPtr hwp = VGAHWPTR(pScrn);
1799
1800        vgaHWUnlock(hwp);
1801        if (!S3ModeInit(pScrn, pScrn->currentMode))
1802                return FALSE;
1803
1804        return TRUE;
1805}
1806
1807
1808static void S3Restore(ScrnInfoPtr pScrn)
1809{
1810        S3Ptr pS3 = S3PTR(pScrn);
1811        S3RegPtr restore = &pS3->SavedRegs;
1812        vgaHWPtr hwp = VGAHWPTR(pScrn);
1813        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
1814	int i;
1815
1816	vgaHWProtect(pScrn, TRUE);
1817	WaitQueue(8);
1818
1819	S3BankZero(pScrn);
1820
1821	outw(ADVFUNC_CNTL, 0x0000);
1822
1823	if (pS3->S3NewMMIO) {
1824		outb(vgaCRIndex, 0x53);
1825		outb(vgaCRReg, 0x00);
1826	}
1827
1828	pS3->DacRestore(pScrn);
1829
1830	if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
1831		outb(vgaCRIndex, 0x5c);
1832		outb(vgaCRReg, restore->s3syssave[0x0c + 16]);
1833	}
1834
1835	for(i=32; i<46; i++) {
1836		outb(vgaCRIndex, 0x40 + i);
1837		outb(vgaCRReg, restore->s3syssave[i]);
1838	}
1839
1840	for(i=0; i<16; i++) {
1841		if (!((1 << i) & 0x673b))
1842			continue;
1843		outb(vgaCRIndex, 0x50 + i);
1844		outb(vgaCRReg, restore->s3syssave[i+16]);
1845	}
1846
1847	for(i=0; i<5; i++) {
1848		outb(vgaCRIndex, 0x30 + i);
1849		outb(vgaCRReg, restore->s3save[i]);
1850		outb(vgaCRIndex, 0x38 + i);
1851		outb(vgaCRReg, restore->s3save[i + 5]);
1852	}
1853
1854	for(i=0; i<16; i++) {
1855		outb(vgaCRIndex, 0x40 + i);
1856		outb(vgaCRReg, restore->s3syssave[i]);
1857	}
1858
1859	outb(vgaCRIndex, 0x45);
1860	inb(vgaCRReg);
1861	outb(vgaCRIndex, 0x4a);
1862	for(i=0; i<4; i++)
1863		outb(vgaCRReg, restore->color_stack[i]);
1864
1865	outb(vgaCRIndex, 0x45);
1866	inb(vgaCRReg);
1867	outb(vgaCRIndex, 0x4b);
1868	for(i=4; i<8; i++)
1869		outb(vgaCRReg, restore->color_stack[i]);
1870
1871        vgaHWRestore(pScrn, &hwp->SavedReg, VGA_SR_ALL);
1872
1873	outb(0x3c2, restore->clock);
1874
1875	vgaHWProtect(pScrn, FALSE);
1876
1877}
1878
1879
1880static void S3LeaveVT(int scrnIndex, int flags)
1881{
1882        ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1883        vgaHWPtr hwp = VGAHWPTR(pScrn);
1884
1885        S3Restore(pScrn);
1886        vgaHWLock(hwp);
1887
1888        return;
1889}
1890
1891
1892static void S3AdjustFrame(int scrnIndex, int x, int y, int flags)
1893{
1894        ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1895        S3Ptr pS3 = S3PTR(pScrn);
1896	S3RegPtr regs = &pS3->ModeRegs;
1897        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
1898	int base, orig_base;
1899	unsigned char tmp;
1900
1901	if (x > pScrn->displayWidth - pS3->HDisplay)
1902		x = pScrn->displayWidth - pS3->HDisplay;
1903
1904	orig_base = (y * pScrn->displayWidth + x) * pS3->s3Bpp;
1905	base = (orig_base >> 2) & ~1;
1906
1907	/* for IBMRGB and TI only */
1908	if (pS3->RamDac->RamDacType == IBM524A_RAMDAC)
1909	{
1910		int px, py, a;
1911
1912		miPointerGetPosition(inputInfo.pointer, &px, &py);
1913
1914		if (pS3->s3Bpp == 1)
1915			a = 4 - 1;
1916		else
1917			a = 8 - 1;
1918		if (px-x > pS3->HDisplay/2)
1919			base = ((orig_base + a*4) >> 2) & ~1;
1920		base &= ~a;
1921	}
1922
1923	outb(vgaCRIndex, 0x31);
1924	outb(vgaCRReg, ((base & 0x030000) >> 12) | regs->cr31);
1925	regs->cr51 &= ~0x03;
1926	regs->cr51 |= ((base & 0x0c0000) >> 18);
1927	outb(vgaCRIndex, 0x51);
1928	tmp = (inb(vgaCRReg) & ~0x03) | (regs->cr51 & 0x03);
1929	outb(vgaCRReg, tmp);
1930
1931	outw(vgaCRIndex, (base & 0x00ff00) | 0x0c);
1932	outw(vgaCRIndex, ((base & 0x00ff) << 8) | 0x0d);
1933}
1934
1935
1936void S3Regdump(ScrnInfoPtr pScrn)
1937{
1938        S3Ptr pS3 = S3PTR(pScrn);
1939        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
1940	{
1941		int j;
1942
1943		for(j=0; j<0x100; j++) {
1944			outb(vgaCRIndex, j);
1945			ErrorF("CRTC 0x%x = 0x%x\n", j, inb(vgaCRReg));
1946		}
1947	}
1948#if 0
1949	ErrorF("DAC regs\n");
1950
1951	{
1952		int j;
1953
1954		for(j=0; j<0x100; j++)
1955			ErrorF("0x%x = 0x%x\n", j, S3InTiIndReg(pScrn, j));
1956#if 0
1957		outb(vgaCRIndex, 0x22);
1958		ErrorF("cr22 = 0x%x\n", inb(vgaCRReg));
1959#endif
1960	}
1961#endif
1962}
1963
1964
1965void S3BankZero(ScrnInfoPtr pScrn)
1966{
1967        S3Ptr pS3 = S3PTR(pScrn);
1968	unsigned char tmp;
1969        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
1970
1971	outb(vgaCRIndex, 0x35);
1972	tmp = inb(vgaCRReg) & 0xf0;
1973	outb(vgaCRReg, tmp);
1974
1975	outb(vgaCRIndex, 0x51);
1976	tmp = inb(vgaCRReg) & 0xf3;
1977	outb(vgaCRReg, tmp);
1978}
1979
1980static void
1981S3DisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode,
1982			    int flags)
1983{
1984     S3Ptr pS3 = S3PTR(pScrn);
1985     switch (pS3->Chipset) {
1986     case PCI_CHIP_TRIO64V2_DXGX:
1987     case PCI_CHIP_TRIO:
1988     case PCI_CHIP_AURORA64VP:
1989     case PCI_CHIP_TRIO64UVP:
1990     {
1991	  int srd;
1992
1993	  outb(0x3c4, 0x08);
1994	  outb(0x3c5, 0x06);	  /* unlock extended sequence registers */
1995
1996	  outb(0x3c4, 0x0d);
1997	  srd = inb(0x3c5) & 0xf;  /* clear the sync control bits */
1998
1999	  switch (PowerManagementMode) {
2000	  case DPMSModeOn:
2001	       /* Screen: On; HSync: On, VSync: On */
2002	       break;
2003	  case DPMSModeStandby:
2004	       /* Screen: Off; HSync: Off, VSync: On */
2005	       srd |= 0x10;
2006	       break;
2007	  case DPMSModeSuspend:
2008	       /* Screen: Off; HSync: On, VSync: Off */
2009	       srd |= 0x40;
2010	       break;
2011	  case DPMSModeOff:
2012	       /* Screen: Off; HSync: Off, VSync: Off */
2013	       srd |= 0x50;
2014	       break;
2015	  }
2016	  outb(0x3c4, 0x0d);
2017	  outb(0x3c5, srd);
2018	  break;
2019     }
2020     default:
2021	  vgaHWDPMSSet(pScrn, PowerManagementMode, flags);
2022     }
2023}
2024