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