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