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