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