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