trident_driver.c revision e6f085ba
1/*
2 * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Alan Hourihane not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Alan Hourihane makes no representations
11 * about the suitability of this software for any purpose.  It is provided
12 * "as is" without express or implied warranty.
13 *
14 * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
23 *	    Re-written for XFree86 v4.0
24 *
25 * Previous driver (pre-XFree86 v4.0) by
26 * 	    Alan Hourihane, alanh@fairlite.demon.co.uk
27 *	    David Wexelblat (major contributor)
28 *	    Massimiliano Ghilardi, max@Linuz.sns.it, some fixes to the
29 *				   clockchip programming code.
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include "fb.h"
37
38#include "mibank.h"
39#include "micmap.h"
40#include "xf86.h"
41#include "xf86_OSproc.h"
42#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
43#include "xf86Resources.h"
44#include "xf86RAC.h"
45#endif
46#include "xf86PciInfo.h"
47#include "xf86Pci.h"
48#include "xf86cmap.h"
49#include "vgaHW.h"
50
51#include "vbe.h"
52#include "dixstruct.h"
53#include "compiler.h"
54
55#include "mipointer.h"
56
57#include "mibstore.h"
58#include "shadow.h"
59#include "trident.h"
60#include "trident_regs.h"
61
62#ifdef XFreeXDGA
63#define _XF86DGA_SERVER_
64#include <X11/extensions/xf86dgastr.h>
65#endif
66
67#include "globals.h"
68#ifdef HAVE_XEXTPROTO_71
69#include <X11/extensions/dpmsconst.h>
70#else
71#define DPMS_SERVER
72#include <X11/extensions/dpms.h>
73#endif
74
75
76#include "xf86xv.h"
77
78static const OptionInfoRec * TRIDENTAvailableOptions(int chipid, int busid);
79static void	TRIDENTIdentify(int flags);
80static Bool	TRIDENTProbe(DriverPtr drv, int flags);
81static Bool	TRIDENTPreInit(ScrnInfoPtr pScrn, int flags);
82static Bool	TRIDENTScreenInit(int Index, ScreenPtr pScreen, int argc,
83			      char **argv);
84static Bool	TRIDENTEnterVT(int scrnIndex, int flags);
85static void	TRIDENTLeaveVT(int scrnIndex, int flags);
86static Bool	TRIDENTCloseScreen(int scrnIndex, ScreenPtr pScreen);
87static Bool	TRIDENTSaveScreen(ScreenPtr pScreen, int mode);
88
89/* Optional functions */
90static void	TRIDENTFreeScreen(int scrnIndex, int flags);
91static ModeStatus TRIDENTValidMode(int scrnIndex, DisplayModePtr mode,
92				   Bool verbose, int flags);
93
94/* Internally used functions */
95static Bool	TRIDENTMapMem(ScrnInfoPtr pScrn);
96static Bool	TRIDENTUnmapMem(ScrnInfoPtr pScrn);
97static void	TRIDENTSave(ScrnInfoPtr pScrn);
98static void	TRIDENTRestore(ScrnInfoPtr pScrn);
99static Bool	TRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
100static void 	TRIDENTBlockHandler(int, pointer, pointer, pointer);
101
102static void	TRIDENTEnableMMIO(ScrnInfoPtr pScrn);
103static void	TRIDENTDisableMMIO(ScrnInfoPtr pScrn);
104static void	PC98TRIDENTInit(ScrnInfoPtr pScrn);
105static void	PC98TRIDENTEnable(ScrnInfoPtr pScrn);
106static void	PC98TRIDENTDisable(ScrnInfoPtr pScrn);
107static void	PC98TRIDENT96xxInit(ScrnInfoPtr pScrn);
108static void	PC98TRIDENT96xxEnable(ScrnInfoPtr pScrn);
109static void	PC98TRIDENT96xxDisable(ScrnInfoPtr pScrn);
110static void	PC98TRIDENT9385Init(ScrnInfoPtr pScrn);
111static void	PC98TRIDENT9385Enable(ScrnInfoPtr pScrn);
112static void	PC98TRIDENT9385Disable(ScrnInfoPtr pScrn);
113static int      TRIDENTLcdDisplaySize (xf86MonPtr pMon);
114
115/*
116 * This is intentionally screen-independent.  It indicates the binding
117 * choice made in the first PreInit.
118 */
119static int pix24bpp = 0;
120
121#define TRIDENT_VERSION 4000
122#define TRIDENT_NAME "TRIDENT"
123#define TRIDENT_DRIVER_NAME "trident"
124#define TRIDENT_MAJOR_VERSION PACKAGE_VERSION_MAJOR
125#define TRIDENT_MINOR_VERSION PACKAGE_VERSION_MINOR
126#define TRIDENT_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
127
128/*
129 * This contains the functions needed by the server after loading the driver
130 * module.  It must be supplied, and gets passed back by the SetupProc
131 * function in the dynamic case.  In the static case, a reference to this
132 * is compiled in, and this requires that the name of this DriverRec be
133 * an upper-case version of the driver name.
134 */
135
136_X_EXPORT DriverRec TRIDENT = {
137    TRIDENT_VERSION,
138    TRIDENT_DRIVER_NAME,
139    TRIDENTIdentify,
140    TRIDENTProbe,
141    TRIDENTAvailableOptions,
142    NULL,
143    0
144};
145
146static SymTabRec TRIDENTChipsets[] = {
147    { TVGA9000,			"tvga9000" },
148    { TVGA9000i,		"tvga9000i" },
149    { TVGA8900C,		"tvga8900c" },
150    { TVGA8900D,		"tvga8900d" },
151    { TVGA9200CXr,		"tvga9200cxr" },
152    { TGUI9400CXi,		"tgui9400cxi" },
153    { CYBER9320,		"cyber9320" },
154    { CYBER9388,		"cyber9388" },
155    { CYBER9397,		"cyber9397" },
156    { CYBER9397DVD,		"cyber9397dvd" },
157    { CYBER9520,		"cyber9520" },
158    { CYBER9525DVD,		"cyber9525dvd" },
159    { CYBERBLADEE4,		"cyberblade/e4" },
160    { TGUI9420DGi,		"tgui9420dgi" },
161    { TGUI9440AGi,		"tgui9440agi" },
162    { TGUI9660,			"tgui9660" },
163    { TGUI9680,			"tgui9680" },
164    { PROVIDIA9682,		"providia9682" },
165    { PROVIDIA9685,		"providia9685" },
166    { CYBER9382,		"cyber9382" },
167    { CYBER9385,		"cyber9385" },
168    { IMAGE975,			"3dimage975" },
169    { IMAGE985,			"3dimage985" },
170    { BLADE3D,			"blade3d" },
171    { CYBERBLADEI7,		"cyberbladei7" },
172    { CYBERBLADEI7D,		"cyberbladei7d" },
173    { CYBERBLADEI1,		"cyberbladei1" },
174    { CYBERBLADEI1D,		"cyberbladei1d" },
175    { CYBERBLADEAI1,		"cyberbladeAi1" },
176    { CYBERBLADEAI1D,		"cyberbladeAi1d" },
177    { BLADEXP,			"bladeXP" },
178    { CYBERBLADEXPAI1,		"cyberbladeXPAi1" },
179    { CYBERBLADEXP4,		"cyberbladeXP4" },
180    { XP5,			"XP5" },
181    { -1,				NULL }
182};
183
184#ifdef HAVE_ISA
185static IsaChipsets TRIDENTISAchipsets[] = {
186    { TVGA9000,			RES_EXCLUSIVE_VGA },
187    { TVGA9000i,		RES_EXCLUSIVE_VGA },
188    { TVGA8900C,		RES_EXCLUSIVE_VGA },
189    { TVGA8900D,		RES_EXCLUSIVE_VGA },
190    { TVGA9200CXr,		RES_EXCLUSIVE_VGA },
191    { TGUI9400CXi,		RES_EXCLUSIVE_VGA },
192    { CYBER9320,		RES_EXCLUSIVE_VGA },
193    { TGUI9440AGi,		RES_EXCLUSIVE_VGA },
194    { -1,			RES_UNDEFINED }
195};
196#endif
197
198static PciChipsets TRIDENTPciChipsets[] = {
199    { CYBER9320,	PCI_CHIP_9320,	RES_SHARED_VGA },
200    { CYBER9388,	PCI_CHIP_9388,	RES_SHARED_VGA },
201    { CYBER9397,	PCI_CHIP_9397,	RES_SHARED_VGA },
202    { CYBER9397DVD,	PCI_CHIP_939A,	RES_SHARED_VGA },
203    { CYBER9520,	PCI_CHIP_9520,	RES_SHARED_VGA },
204    { CYBER9525DVD,	PCI_CHIP_9525,	RES_SHARED_VGA },
205    { CYBERBLADEE4,	PCI_CHIP_9540,	RES_SHARED_VGA },
206    { TGUI9420DGi,	PCI_CHIP_9420,	RES_SHARED_VGA },
207    { TGUI9440AGi,	PCI_CHIP_9440,	RES_SHARED_VGA },
208    { TGUI9660,		PCI_CHIP_9660,	RES_SHARED_VGA },
209    { TGUI9680,		PCI_CHIP_9660,	RES_SHARED_VGA },
210    { PROVIDIA9682,	PCI_CHIP_9660,	RES_SHARED_VGA },
211    { PROVIDIA9685,	PCI_CHIP_9660,	RES_SHARED_VGA },
212    { CYBER9382,	PCI_CHIP_9660,	RES_SHARED_VGA },
213    { CYBER9385,	PCI_CHIP_9660,	RES_SHARED_VGA },
214    { IMAGE975,		PCI_CHIP_9750,	RES_SHARED_VGA },
215    { IMAGE985,		PCI_CHIP_9850,	RES_SHARED_VGA },
216    { BLADE3D,		PCI_CHIP_9880,	RES_SHARED_VGA },
217    { CYBERBLADEI7,	PCI_CHIP_8400,	RES_SHARED_VGA },
218    { CYBERBLADEI7D,	PCI_CHIP_8420,	RES_SHARED_VGA },
219    { CYBERBLADEI1,	PCI_CHIP_8500,	RES_SHARED_VGA },
220    { CYBERBLADEI1D,	PCI_CHIP_8520,	RES_SHARED_VGA },
221    { CYBERBLADEAI1,	PCI_CHIP_8600,	RES_SHARED_VGA },
222    { CYBERBLADEAI1D,	PCI_CHIP_8620,	RES_SHARED_VGA },
223    { BLADEXP,		PCI_CHIP_9910,	RES_SHARED_VGA },
224    { CYBERBLADEXPAI1,	PCI_CHIP_8820,	RES_SHARED_VGA },
225    { CYBERBLADEXP4,	PCI_CHIP_2100,	RES_SHARED_VGA },
226    { XP5,		PCI_CHIP_2200,	RES_SHARED_VGA },
227    { -1,		-1,		RES_UNDEFINED }
228};
229
230typedef enum {
231    OPTION_ACCELMETHOD,
232    OPTION_SW_CURSOR,
233    OPTION_PCI_RETRY,
234    OPTION_RGB_BITS,
235    OPTION_NOACCEL,
236    OPTION_SETMCLK,
237    OPTION_MUX_THRESHOLD,
238    OPTION_SHADOW_FB,
239    OPTION_ROTATE,
240    OPTION_MMIO_ONLY,
241    OPTION_VIDEO_KEY,
242    OPTION_NOMMIO,
243    OPTION_NOPCIBURST,
244    OPTION_CYBER_SHADOW,
245    OPTION_CYBER_STRETCH,
246    OPTION_XV_HSYNC,
247    OPTION_XV_VSYNC,
248    OPTION_XV_BSKEW,
249    OPTION_XV_RSKEW,
250    OPTION_FP_DELAY,
251    OPTION_1400_DISPLAY,
252    OPTION_DISPLAY,
253    OPTION_GB,
254    OPTION_TV_CHIPSET,
255    OPTION_TV_SIGNALMODE
256} TRIDENTOpts;
257
258static const OptionInfoRec TRIDENTOptions[] = {
259    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0}, FALSE },
260    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
261    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
262    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
263    { OPTION_SETMCLK,		"SetMClk",	OPTV_FREQ,	{0}, FALSE },
264    { OPTION_MUX_THRESHOLD,	"MUXThreshold",	OPTV_INTEGER,	{0}, FALSE },
265    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
266    { OPTION_ROTATE,  	        "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
267    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
268    { OPTION_NOMMIO,		"NoMMIO",	OPTV_BOOLEAN,	{0}, FALSE },
269    { OPTION_NOPCIBURST,	"NoPciBurst",	OPTV_BOOLEAN,	{0}, FALSE },
270    { OPTION_MMIO_ONLY,		"MMIOonly",	OPTV_BOOLEAN,	{0}, FALSE },
271    { OPTION_CYBER_SHADOW,	"CyberShadow",	OPTV_BOOLEAN,	{0}, FALSE },
272    { OPTION_CYBER_STRETCH,	"CyberStretch",	OPTV_BOOLEAN,	{0}, FALSE },
273    { OPTION_XV_HSYNC,          "XvHsync",      OPTV_INTEGER,   {0}, FALSE },
274    { OPTION_XV_VSYNC,          "XvVsync",      OPTV_INTEGER,   {0}, FALSE },
275    { OPTION_XV_BSKEW,          "XvBskew",      OPTV_INTEGER,   {0}, FALSE },
276    { OPTION_XV_RSKEW,          "XvRskew",      OPTV_INTEGER,   {0}, FALSE },
277    { OPTION_FP_DELAY,          "FpDelay",      OPTV_INTEGER,   {0}, FALSE },
278    { OPTION_1400_DISPLAY,	"Display1400",	OPTV_BOOLEAN,	{0}, FALSE },
279    { OPTION_DISPLAY,		"Display",	OPTV_ANYSTR,	{0}, FALSE },
280    { OPTION_GB,		"GammaBrightness",	OPTV_ANYSTR,	{0}, FALSE },
281    { OPTION_TV_CHIPSET,        "TVChipset",    OPTV_ANYSTR,    {0}, FALSE },
282    { OPTION_TV_SIGNALMODE,     "TVSignal",     OPTV_INTEGER,   {0}, FALSE },
283    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
284};
285
286/* Clock Limits */
287static int ClockLimit[] = {
288	80000,
289	80000,
290	80000,
291	80000,
292	80000,
293	80000,
294	80000,
295	80000,
296	80000,
297	80000,
298	80000,
299	80000,
300	80000,
301	80000,
302	90000,
303	90000,
304	135000,
305	135000,
306	170000,
307	170000,
308	170000,
309	170000,
310	170000,
311	170000,
312	170000,
313	230000,
314	230000,
315	230000,
316	230000,
317	230000,
318	230000,
319	230000,
320	230000,
321	230000,
322	230000,
323	230000,
324	230000,
325	230000,
326	230000,
327	230000,
328	230000,
329};
330
331static int ClockLimit16bpp[] = {
332	40000,
333	40000,
334	40000,
335	40000,
336	40000,
337	40000,
338	40000,
339	40000,
340	40000,
341	40000,
342	40000,
343	40000,
344	40000,
345	40000,
346	45000,
347	45000,
348	90000,
349	90000,
350	135000,
351	135000,
352	170000,
353	170000,
354	170000,
355	170000,
356	170000,
357	230000,
358	230000,
359	230000,
360	230000,
361	230000,
362	230000,
363	230000,
364	230000,
365	230000,
366	230000,
367	230000,
368	230000,
369	230000,
370	230000,
371	230000,
372	230000,
373};
374
375static int ClockLimit24bpp[] = {
376	25180,
377	25180,
378	25180,
379	25180,
380	25180,
381	25180,
382	25180,
383	25180,
384	25180,
385	25180,
386	25180,
387	25180,
388	25180,
389	25180,
390	25180,
391	25180,
392	40000,
393	40000,
394	70000,
395	70000,
396	70000,
397	115000,
398	115000,
399	115000,
400	115000,
401	115000,
402	115000,
403	115000,
404	115000,
405	115000,
406	115000,
407	115000,
408	115000,
409	115000,
410	115000,
411	115000,
412	115000,
413	115000,
414	115000,
415	115000,
416	115000,
417};
418
419static int ClockLimit32bpp[] = {
420	25180,
421	25180,
422	25180,
423	25180,
424	25180,
425	25180,
426	25180,
427	25180,
428	25180,
429	25180,
430	25180,
431	25180,
432	25180,
433	25180,
434	25180,
435	25180,
436	40000,
437	40000,
438	70000,
439	70000,
440	70000,
441	115000,
442	115000,
443	115000,
444	115000,
445	115000,
446	115000,
447	115000,
448	115000,
449	115000,
450	115000,
451	115000,
452	115000,
453	115000,
454	115000,
455	115000,
456	115000,
457	115000,
458	115000,
459	115000,
460	115000,
461	115000,
462};
463
464/*
465 * These are fixed modelines for all physical display dimensions the
466 *  chipsets supports on FPs. Most of them are not tested yet.
467 */
468#if 0
469tridentLCD LCD[] = {   /* 0    3    4    5   6    7    10   11  16 */
470    { 0,"640x480",25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08},
471    { 1,"800x600",40000,0x7f,0x99,0x69,0x99,0x72,0xf0,0x59,0x2d,0x5e,0x08},
472    { 2,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08},
473    { 3,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, /*0x96*/
474    { 4,"1280x1024",108000,0xa3,0x6,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08},
475    { 5,"1024x600",50500 ,0xa3,0x6,0x8f,0xa0,0xb,0x3e,0xea,0x8c,0xb,0x08},
476    { 0xff,"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
477};
478#else
479#if 0
480tridentLCD LCD[] = {
481    { 1,640,480,25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08},
482    { 3,800,600,40000,0x7f,0x82,0x6b,0x1b,0x72,0xf8,0x58,0x8c,0x72,0x08},
483    { 2,1024,768,65000,0xa3,/*0x6*/0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x24,0x0a,0x08},
484    { 0,1280,1024,108000,0xce,0x81,0xa6,0x9a,0x27,0x50,0x00,0x03,0x26,0xa8},
485    { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
486};
487#else
488tridentLCD LCD[] = {
489    { 1,640,480,25200,0x5f,0x80,0x52,0x1e,0xb,0x3e,0xea,0x0c,0xb,0x08},
490    { 3,800,600,40000,0x7f,0x00,0x69,0x7f,0x72,0xf0,0x59,0x0d,0x00,0x08},
491    { 2,1024,768,65000,0xa3,0x00,0x84,0x94,0x24,0xf5,0x03,0x09,0x24,0x08},
492    { 0,1280,1024,108000,0xce,0x91,0xa6,0x14,0x28,0x5a,0x01,0x04,0x28,0xa8},
493    { 4,1400,1050,122000,0xe6,0x8d,0xba,0x1d,0x38,0x00,0x1c,0x28,0x28,0xf8},
494    { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
495};
496#endif
497#endif
498
499#ifdef XFree86LOADER
500
501static MODULESETUPPROTO(tridentSetup);
502
503static XF86ModuleVersionInfo tridentVersRec =
504{
505	"trident",
506	MODULEVENDORSTRING,
507	MODINFOSTRING1,
508	MODINFOSTRING2,
509	XORG_VERSION_CURRENT,
510	TRIDENT_MAJOR_VERSION, TRIDENT_MINOR_VERSION, TRIDENT_PATCHLEVEL,
511	ABI_CLASS_VIDEODRV,			/* This is a video driver */
512	ABI_VIDEODRV_VERSION,
513	MOD_CLASS_VIDEODRV,
514	{0,0,0,0}
515};
516
517_X_EXPORT XF86ModuleData tridentModuleData = {
518	&tridentVersRec,
519	tridentSetup,
520	NULL
521};
522
523pointer
524tridentSetup(pointer module, pointer opts, int *errmaj, int *errmin)
525{
526    static Bool setupDone = FALSE;
527
528    if (!setupDone) {
529	setupDone = TRUE;
530	xf86AddDriver(&TRIDENT, module, 0);
531	return (pointer)TRUE;
532    }
533
534    if (errmaj) *errmaj = LDR_ONCEONLY;
535    return NULL;
536}
537
538#endif /* XFree86LOADER */
539
540static Bool
541TRIDENTGetRec(ScrnInfoPtr pScrn)
542{
543    /*
544     * Allocate an TRIDENTRec, and hook it into pScrn->driverPrivate.
545     * pScrn->driverPrivate is initialised to NULL, so we can check if
546     * the allocation has already been done.
547     */
548    if (pScrn->driverPrivate != NULL)
549	return TRUE;
550
551    pScrn->driverPrivate = xnfcalloc(sizeof(TRIDENTRec), 1);
552    /* Initialise it */
553
554    return TRUE;
555}
556
557static void
558TRIDENTFreeRec(ScrnInfoPtr pScrn)
559{
560    if (pScrn->driverPrivate == NULL)
561	return;
562    xfree(pScrn->driverPrivate);
563    pScrn->driverPrivate = NULL;
564}
565
566static void
567TRIDENTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
568{
569    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
570    CARD8 DPMSCont, PMCont, temp;
571
572    if (!pScrn->vtSema)
573	return;
574
575    OUTB(0x3C4, 0x0E);
576    temp = INB(0x3C5);
577    OUTB(0x3C5, 0xC2);
578    OUTB(0x83C8, 0x04); /* Read DPMS Control */
579    PMCont = INB(0x83C6) & 0xFC;
580    OUTB(0x3CE, 0x23);
581    DPMSCont = INB(0x3CF) & 0xFC;
582    switch (PowerManagementMode)
583    {
584	case DPMSModeOn:
585		/* Screen: On, HSync: On, VSync: On */
586		PMCont |= 0x03;
587		DPMSCont |= 0x00;
588		break;
589	case DPMSModeStandby:
590		/* Screen: Off, HSync: Off, VSync: On */
591		PMCont |= 0x02;
592		DPMSCont |= 0x01;
593		break;
594	case DPMSModeSuspend:
595		/* Screen: Off, HSync: On, VSync: Off */
596		PMCont |= 0x02;
597		DPMSCont |= 0x02;
598		break;
599	case DPMSModeOff:
600		/* Screen: Off, HSync: Off, VSync: Off */
601		PMCont |= 0x00;
602		DPMSCont |= 0x03;
603		break;
604    }
605    OUTB(0x3CF, DPMSCont);
606    OUTB(0x83C8, 0x04);
607    OUTB(0x83C6, PMCont);
608    OUTW(0x3C4, (temp<<8) | 0x0E);
609}
610
611static void
612TRIDENTBlockHandler (
613    int i,
614    pointer     blockData,
615    pointer     pTimeout,
616    pointer     pReadmask
617){
618    ScreenPtr      pScreen = screenInfo.screens[i];
619    ScrnInfoPtr    pScrn = xf86Screens[i];
620    TRIDENTPtr     pTrident = TRIDENTPTR(pScrn);
621
622    pScreen->BlockHandler = pTrident->BlockHandler;
623    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
624    pScreen->BlockHandler = TRIDENTBlockHandler;
625
626    if(pTrident->VideoTimerCallback) {
627	UpdateCurrentTime();
628	(*pTrident->VideoTimerCallback)(pScrn, currentTime.milliseconds);
629    }
630}
631
632static const OptionInfoRec *
633TRIDENTAvailableOptions(int chipid, int busid)
634{
635    return TRIDENTOptions;
636}
637
638/* Mandatory */
639static void
640TRIDENTIdentify(int flags)
641{
642    xf86PrintChipsets(TRIDENT_NAME, "driver for Trident chipsets", TRIDENTChipsets);
643}
644
645Bool
646TRIDENTClockSelect(ScrnInfoPtr pScrn, int no)
647{
648    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
649    unsigned char temp;
650
651    /*
652     * CS0 and CS1 are in MiscOutReg
653     *
654     * For 8900B, 8900C, 8900CL and 9000, CS2 is bit 0 of
655     * New Mode Control Register 2.
656     *
657     * For 8900CL, CS3 is bit 4 of Old Mode Control Register 1.
658     *
659     * For 9000, CS3 is bit 6 of New Mode Control Register 2.
660     *
661     * For TGUI, we don't use the ClockSelect function at all.
662     */
663     switch(no) {
664	case CLK_REG_SAVE:
665	    pTrident->SaveClock1 = INB(0x3CC);
666	    if (pTrident->Chipset != TVGA8800CS) {
667		if ( (pScrn->numClocks == 16) &&
668		     (pTrident->Chipset != TVGA9000) &&
669		     (pTrident->Chipset != TVGA9000i) )
670		{
671		    OUTW(0x3C4, 0x000B);	/* Switch to Old Mode */
672		    OUTB(0x3C4, 0x0E); pTrident->SaveClock3 = INB(0x3C5);
673		}
674		OUTB(0x3C4, 0x0B);
675		INB(0x3C5);		/* Now to New Mode */
676		OUTB(0x3C4, 0x0D); pTrident->SaveClock2 = INB(0x3C5);
677	    }
678	    break;
679	case CLK_REG_RESTORE:
680	    OUTB(0x3C2, pTrident->SaveClock1);
681	    if (pTrident->Chipset != TVGA8800CS) {
682		if ( (pScrn->numClocks == 16) &&
683		     (pTrident->Chipset != TVGA9000) &&
684		     (pTrident->Chipset != TVGA9000i) )
685		{
686			OUTW(0x3C4, 0x000B);	/* Switch to Old Mode */
687			OUTW(0x3C4, (pTrident->SaveClock3 << 8) | 0x0E);
688		}
689		OUTB(0x3C4, 0x0B);
690		INB(0x3C5);		/* Now to New Mode */
691		OUTW(0x3C4, (pTrident->SaveClock2 << 8) | 0x0D);
692	    }
693	    break;
694	default:
695	    /*
696	     * Do CS0 and CS1
697	     */
698	    temp = INB(0x3CC);
699	    OUTB(0x3C2, (temp & 0xF3) | ((no << 2) & 0x0C));
700	    if (pTrident->Chipset != TVGA8800CS) {
701		if ( (pScrn->numClocks == 16) &&
702		     (pTrident->Chipset != TVGA9000) &&
703		     (pTrident->Chipset != TVGA9000i) )
704		{
705			/*
706			 * Go to Old Mode for CS3.
707		 	 */
708			OUTW(0x3C4, 0x000B);	/* Switch to Old Mode */
709			OUTB(0x3C4, 0x0E);
710			temp = INB(0x3C5) & 0xEF;
711			temp |= (no & 0x08) << 1;
712			OUTB(0x3C5, temp);
713		}
714		/*
715	  	 * Go to New Mode for CS2 and TVGA9000 CS3.
716	  	 */
717		OUTB(0x3C4, 0x0B);
718		INB(0x3C5);		/* Now to New Mode */
719		OUTB(0x3C4, 0x0D);
720		/*
721		 * Bits 1 & 2 are dividers - set to 0 to get no
722		 * clock division.
723		 */
724		temp = INB(0x3C5) & 0xF8;
725		temp |= (no & 0x04) >> 2;
726		if ( (pTrident->Chipset == TVGA9000) ||
727		     (pTrident->Chipset == TVGA9000i) )
728		{
729			temp &= ~0x40;
730			temp |= (no & 0x08) << 3;
731		}
732		OUTB(0x3C5, temp);
733	}
734    }
735    return(TRUE);
736}
737
738#ifdef HAVE_ISA
739static int
740TridentFindIsaDevice(GDevPtr dev)
741{
742    int found = -1;
743    unsigned char temp, origVal, newVal;
744
745    /*
746     * Check first that we have a Trident card.
747     */
748    outb(0x3C4, 0x0B);
749    temp = inb(0x3C5);	/* Save old value */
750    outb(0x3C4, 0x0B);	/* Switch to Old Mode */
751    outb(0x3C5, 0x00);
752    inb(0x3C5);		/* Now to New Mode */
753    outb(0x3C4, 0x0E);
754    origVal = inb(0x3C5);
755    outb(0x3C5, 0x00);
756    newVal = inb(0x3C5) & 0x0F;
757    outb(0x3C5, (origVal ^ 0x02));
758
759    /*
760     * Is it a Trident card ??
761     */
762    if (newVal != 2) {
763	/*
764	 * Nope, so quit
765	 */
766	outb(0x3C4, 0x0B);	/* Restore value of 0x0B */
767	outb(0x3C5, temp);
768	outb(0x3C4, 0x0E);
769	outb(0x3C5, origVal);
770	return found;
771    }
772
773    outb(0x3C4, 0x0B);
774    temp = inb(0x3C5);
775    switch (temp) {
776	case 0x01:
777	    found = TVGA8800BR;
778	    break;
779	case 0x02:
780	    found = TVGA8800CS;
781	    break;
782	case 0x03:
783	    found = TVGA8900B;
784	    break;
785	case 0x04:
786	case 0x13:
787	    found = TVGA8900C;
788	    break;
789	case 0x23:
790	    found = TVGA9000;
791	    break;
792	case 0x33:
793	    found = TVGA8900D;
794	    break;
795	case 0x43:
796	    found = TVGA9000i;
797	    break;
798	case 0x53:
799	    found = TVGA9200CXr;
800	    break;
801	case 0x63:
802	    found = TVGA9100B;
803	    break;
804	case 0x73:
805	case 0xC3:
806	    found = TGUI9420DGi;
807	    break;
808	case 0x83:
809	    found = TVGA8200LX;
810	    break;
811	case 0x93:
812	    found = TGUI9400CXi;
813	    break;
814	case 0xA3:
815	    found = CYBER9320;
816	    break;
817	case 0xD3:
818	    found = TGUI9660;
819	    break;
820	case 0xE3:
821	    found = TGUI9440AGi;
822	    break;
823	case 0xF3:
824	    found = TGUI9430DGi;
825	    break;
826    }
827    return found;
828}
829#endif
830
831
832/* Mandatory */
833static Bool
834TRIDENTProbe(DriverPtr drv, int flags)
835{
836    int i;
837    GDevPtr *devSections;
838    int *usedChips = NULL;
839    int numDevSections;
840    int numUsed;
841    Bool foundScreen = FALSE;
842
843    if ((numDevSections = xf86MatchDevice(TRIDENT_DRIVER_NAME,
844					  &devSections)) <= 0) {
845	/*
846	 * There's no matching device section in the config file, so quit
847	 * now.
848	 */
849	return FALSE;
850    }
851
852    /*
853     * While we're VGA-dependent, can really only have one such instance, but
854     * we'll ignore that.
855     */
856
857    /*
858     * We need to probe the hardware first.  We then need to see how this
859     * fits in with what is given in the config file, and allow the config
860     * file info to override any contradictions.
861     */
862
863    /*
864     * All of the cards this driver supports are PCI, so the "probing" just
865     * amounts to checking the PCI data that the server has already collected.
866     */
867#ifndef XSERVER_LIBPCIACCESS
868    if (xf86GetPciVideoInfo()== NULL) {
869	return FALSE;
870    }
871#endif
872    {
873    	numUsed = xf86MatchPciInstances(TRIDENT_NAME, PCI_VENDOR_TRIDENT,
874		   TRIDENTChipsets, TRIDENTPciChipsets, devSections,
875		   numDevSections, drv, &usedChips);
876
877	if (numUsed > 0) {
878	    if (flags & PROBE_DETECT)
879		foundScreen = TRUE;
880	    else for (i = 0; i < numUsed; i++) {
881		ScrnInfoPtr pScrn = NULL;
882
883		if ((pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
884						       TRIDENTPciChipsets, NULL,
885						       NULL, NULL, NULL, NULL))) {
886		    /* Fill in what we can of the ScrnInfoRec */
887		    pScrn->driverVersion = TRIDENT_VERSION;
888		    pScrn->driverName	 = TRIDENT_DRIVER_NAME;
889		    pScrn->name		 = TRIDENT_NAME;
890		    pScrn->Probe	 = TRIDENTProbe;
891		    pScrn->PreInit	 = TRIDENTPreInit;
892		    pScrn->ScreenInit	 = TRIDENTScreenInit;
893		    pScrn->SwitchMode	 = TRIDENTSwitchMode;
894		    pScrn->AdjustFrame	 = TRIDENTAdjustFrame;
895		    pScrn->EnterVT	 = TRIDENTEnterVT;
896		    pScrn->LeaveVT	 = TRIDENTLeaveVT;
897		    pScrn->FreeScreen	 = TRIDENTFreeScreen;
898		    pScrn->ValidMode	 = TRIDENTValidMode;
899		    foundScreen = TRUE;
900		}
901	    }
902	    xfree(usedChips);
903	}
904    }
905
906#ifdef HAVE_ISA
907    /* Isa Bus */
908    numUsed = xf86MatchIsaInstances(TRIDENT_NAME,TRIDENTChipsets,
909				     TRIDENTISAchipsets,
910				     drv,TridentFindIsaDevice,devSections,
911				     numDevSections,&usedChips);
912    if (numUsed > 0) {
913	if (flags & PROBE_DETECT)
914	    foundScreen = TRUE;
915	else 	for (i = 0; i < numUsed; i++) {
916	    ScrnInfoPtr pScrn = NULL;
917	    if ((pScrn = xf86ConfigIsaEntity(pScrn,0,usedChips[i],
918						  TRIDENTISAchipsets,NULL,
919						  NULL,NULL,NULL,NULL))) {
920		pScrn->driverVersion = TRIDENT_VERSION;
921		pScrn->driverName    = TRIDENT_DRIVER_NAME;
922		pScrn->name          = TRIDENT_NAME;
923		pScrn->Probe         = TRIDENTProbe;
924		pScrn->PreInit       = TRIDENTPreInit;
925		pScrn->ScreenInit    = TRIDENTScreenInit;
926		pScrn->SwitchMode    = TRIDENTSwitchMode;
927		pScrn->AdjustFrame   = TRIDENTAdjustFrame;
928		pScrn->EnterVT       = TRIDENTEnterVT;
929		pScrn->LeaveVT       = TRIDENTLeaveVT;
930		pScrn->FreeScreen    = TRIDENTFreeScreen;
931		pScrn->ValidMode     = TRIDENTValidMode;
932		foundScreen = TRUE;
933	    }
934	}
935	xfree(usedChips);
936    }
937#endif
938
939    xfree(devSections);
940    return foundScreen;
941}
942
943/*
944 * GetAccelPitchValues -
945 *
946 * This function returns a list of display width (pitch) values that can
947 * be used in accelerated mode.
948 */
949static int *
950GetAccelPitchValues(ScrnInfoPtr pScrn)
951{
952    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
953    int *linePitches = NULL;
954    int lines[4] = { 512, 1024, 2048, 4096 }; /* 9440AGi */
955    int i, n = 0;
956
957    if (pTrident->Chipset >= BLADEXP) {
958	lines[0] = 1024;
959	lines[1] = 2048;
960	lines[2] = 4096;
961	lines[3] = 8192;
962    }
963
964    for (i = 0; i < 4; i++) {
965	n++;
966	linePitches = xnfrealloc(linePitches, n * sizeof(int));
967	linePitches[n - 1] = lines[i];
968    }
969
970    /* Mark the end of the list */
971    if (n > 0) {
972	linePitches = xnfrealloc(linePitches, (n + 1) * sizeof(int));
973	linePitches[n] = 0;
974    }
975    return linePitches;
976}
977
978static void
979TRIDENTProbeDDC(ScrnInfoPtr pScrn, int index)
980{
981    vbeInfoPtr pVbe;
982    if (xf86LoadSubModule(pScrn, "vbe")) {
983	pVbe = VBEInit(NULL,index);
984	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
985	vbeFree(pVbe);
986    }
987}
988
989/* Mandatory */
990static Bool
991TRIDENTPreInit(ScrnInfoPtr pScrn, int flags)
992{
993    TRIDENTPtr pTrident;
994    vgaHWPtr hwp;
995    MessageType from;
996    CARD8 videoram, videorammask;
997    char *ramtype = NULL, *chipset = NULL;
998    Bool Support24bpp;
999    int vgaIOBase;
1000    float mclk;
1001    double real;
1002    int i, NoClocks = 16;
1003    CARD8 revision;
1004    ClockRangePtr clockRanges;
1005    Bool ddcLoaded = FALSE;
1006    xf86MonPtr pMon = NULL;
1007    char *s;
1008    Bool tmp_bool;
1009
1010    /* Allocate the TRIDENTRec driverPrivate */
1011    if (!TRIDENTGetRec(pScrn)) {
1012	return FALSE;
1013    }
1014    pTrident = TRIDENTPTR(pScrn);
1015    pTrident->pScrn = pScrn;
1016
1017    if (pScrn->numEntities > 1)
1018	return FALSE;
1019    /* This is the general case */
1020    for (i = 0; i<pScrn->numEntities; i++) {
1021	pTrident->pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
1022#ifndef XSERVER_LIBPCIACCESS
1023	if (pTrident->pEnt->resources) return FALSE;
1024#endif
1025	pTrident->Chipset = pTrident->pEnt->chipset;
1026	pScrn->chipset = (char *)xf86TokenToString(TRIDENTChipsets,
1027						   pTrident->pEnt->chipset);
1028	/* This driver can handle ISA and PCI buses */
1029	if (pTrident->pEnt->location.type == BUS_PCI) {
1030	    pTrident->PciInfo = xf86GetPciInfoForEntity(pTrident->pEnt->index);
1031#ifndef XSERVER_LIBPCIACCESS
1032	    pTrident->PciTag = PCI_DEV_TAG(pTrident->PciInfo);
1033#endif
1034    	    pTrident->Linear = TRUE;
1035	} else {
1036    	    pTrident->Linear = FALSE;
1037	}
1038    }
1039
1040    if (flags & PROBE_DETECT) {
1041	TRIDENTProbeDDC(pScrn, pTrident->pEnt->index);
1042	return TRUE;
1043    }
1044
1045    /* Set pScrn->monitor */
1046    pScrn->monitor = pScrn->confScreen->monitor;
1047
1048    /*
1049     * The first thing we should figure out is the depth, bpp, etc.
1050     * Our preference for depth 24 is 24bpp, so tell it that too.
1051     */
1052    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb |
1053			    SupportConvert32to24 /*| PreferConvert32to24*/)) {
1054	return FALSE;
1055    } else {
1056	/* Check that the returned depth is one we support */
1057	switch (pScrn->depth) {
1058	case 8:
1059	    if (pScrn->bitsPerPixel != pScrn->depth) {
1060	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1061	     "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n",
1062		       pScrn->depth, pScrn->bitsPerPixel);
1063		return FALSE;
1064	    }
1065	    break;
1066	case 15:
1067	case 16:
1068	    if (pScrn->bitsPerPixel != 16) {
1069	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1070	     "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n",
1071		       pScrn->depth, pScrn->bitsPerPixel);
1072		return FALSE;
1073	    }
1074	    break;
1075	case 24:
1076	    if ((pScrn->bitsPerPixel != 24) && (pScrn->bitsPerPixel != 32)) {
1077	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1078	     "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n",
1079		       pScrn->depth, pScrn->bitsPerPixel);
1080		return FALSE;
1081	    }
1082	    /* OK */
1083	    break;
1084	default:
1085	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1086		       "Given depth (%d) is not supported by this driver\n",
1087		       pScrn->depth);
1088	    return FALSE;
1089	}
1090    }
1091
1092    xf86PrintDepthBpp(pScrn);
1093
1094    /* Get the depth24 pixmap format */
1095    if (pScrn->depth == 24 && pix24bpp == 0)
1096	pix24bpp = xf86GetBppFromDepth(pScrn, 24);
1097
1098    /* The vgahw module should be loaded here when needed */
1099    if (!xf86LoadSubModule(pScrn, "vgahw"))
1100	return FALSE;
1101
1102    /*
1103     * Allocate a vgaHWRec
1104     */
1105    if (!vgaHWGetHWRec(pScrn))
1106	return FALSE;
1107
1108    hwp = VGAHWPTR(pScrn);
1109    vgaHWGetIOBase(hwp);
1110    vgaIOBase = hwp->IOBase;
1111    pTrident->PIOBase = hwp->PIOOffset;
1112
1113#ifndef XSERVER_LIBPCIACCESS
1114    xf86SetOperatingState(resVga, pTrident->pEnt->index, ResUnusedOpr);
1115#endif
1116
1117    /* The ramdac module should be loaded here when needed */
1118    if (!xf86LoadSubModule(pScrn, "ramdac"))
1119	return FALSE;
1120
1121    /*
1122     * This must happen after pScrn->display has been set because
1123     * xf86SetWeight references it.
1124     */
1125    if (pScrn->depth > 8) {
1126	/* The defaults are OK for us */
1127	rgb zeros = {0, 0, 0};
1128
1129	if (!xf86SetWeight(pScrn, zeros, zeros)) {
1130	    return FALSE;
1131	} else {
1132	    /* XXX check that weight returned is supported */
1133            ;
1134        }
1135    }
1136
1137    if (!xf86SetDefaultVisual(pScrn, -1)) {
1138	return FALSE;
1139    } else {
1140	/* We don't currently support DirectColor at > 8bpp */
1141	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
1142	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
1143		       " (%s) is not supported at depth %d\n",
1144		       xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
1145	    return FALSE;
1146	}
1147    }
1148
1149    /*
1150     * The new cmap layer needs this to be initialised.
1151     */
1152
1153    {
1154	Gamma zeros = {0.0, 0.0, 0.0};
1155
1156	if (!xf86SetGamma(pScrn, zeros)) {
1157	    return FALSE;
1158	}
1159    }
1160
1161    /* Collect all of the relevant option flags (fill in pScrn->options) */
1162    xf86CollectOptions(pScrn, NULL);
1163
1164    /* Process the options */
1165    if (!(pTrident->Options = xalloc(sizeof(TRIDENTOptions))))
1166	return FALSE;
1167    memcpy(pTrident->Options, TRIDENTOptions, sizeof(TRIDENTOptions));
1168    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTrident->Options);
1169
1170    /* Set the bits per RGB for 8bpp mode */
1171    if (pScrn->depth == 8) {
1172	/* XXX This is here just to test options. */
1173	/* Default to 8 */
1174	pScrn->rgbBits = 6;
1175#if 0
1176	if (xf86GetOptValInteger(pTrident->Options, OPTION_RGB_BITS,
1177				 &pScrn->rgbBits)) {
1178	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n",
1179		       pScrn->rgbBits);
1180	}
1181#endif
1182    }
1183    from = X_DEFAULT;
1184
1185    pTrident->useEXA = FALSE;
1186    if ((s = (char *)xf86GetOptValString(pTrident->Options,
1187					 OPTION_ACCELMETHOD))) {
1188	if (!xf86NameCmp(s, "EXA")) {
1189	    pTrident->useEXA = TRUE;
1190	    from = X_CONFIG;
1191	}
1192	else if (!xf86NameCmp(s, "XAA")) {
1193	    pTrident->useEXA = FALSE;
1194	    from = X_CONFIG;
1195	}
1196    }
1197    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
1198	       pTrident->useEXA ? "EXA" : "XAA");
1199
1200    pTrident->HWCursor = TRUE;
1201    if (xf86ReturnOptValBool(pTrident->Options, OPTION_SW_CURSOR, FALSE)) {
1202	from = X_CONFIG;
1203	pTrident->HWCursor = FALSE;
1204    }
1205    if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOACCEL, FALSE)) {
1206	pTrident->NoAccel = TRUE;
1207	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
1208    }
1209    if (xf86ReturnOptValBool(pTrident->Options, OPTION_PCI_RETRY, FALSE)) {
1210	pTrident->UsePCIRetry = TRUE;
1211	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
1212    }
1213    pTrident->UsePCIBurst = TRUE;
1214    if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOPCIBURST, FALSE)) {
1215	pTrident->UsePCIBurst = FALSE;
1216	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI Burst disbled\n");
1217    }
1218    /* Display Size override moved to DDC section */
1219    if(xf86GetOptValInteger(pTrident->Options, OPTION_VIDEO_KEY,
1220						&(pTrident->videoKey))) {
1221	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
1222							pTrident->videoKey);
1223    } else {
1224	pTrident->videoKey =  (1 << pScrn->offset.red) |
1225			(1 << pScrn->offset.green) |
1226			(((pScrn->mask.blue >> pScrn->offset.blue) - 1)
1227			<< pScrn->offset.blue);
1228    }
1229    if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOMMIO, FALSE)) {
1230	pTrident->NoMMIO = TRUE;
1231	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO Disabled\n");
1232    }
1233    if (xf86ReturnOptValBool(pTrident->Options, OPTION_MMIO_ONLY, FALSE)) {
1234	if (pTrident->NoMMIO)
1235	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "MMIO only cannot be set"
1236		       " with NoMMIO\n");
1237	else {
1238	    pTrident->MMIOonly = TRUE;
1239	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO only enabled\n");
1240	}
1241    }
1242
1243    pTrident->dspOverride = 0;
1244    if ((s = xf86GetOptValString(pTrident->Options, OPTION_DISPLAY))) {
1245	if(!xf86NameCmp(s, "CRT")) {
1246	    pTrident->dspOverride = CRT_ACTIVE;
1247	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD off CRT on\n");
1248	} else if (!xf86NameCmp(s, "LCD")) {
1249	    pTrident->dspOverride = LCD_ACTIVE;
1250	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT off\n");
1251	} else if (!xf86NameCmp(s, "Dual")) {
1252	    pTrident->dspOverride = LCD_ACTIVE | CRT_ACTIVE;
1253	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT on\n");
1254	} else
1255	    xf86DrvMsg(pScrn->scrnIndex,X_ERROR,
1256		       "%s is an unknown display option\n",s);
1257    }
1258    if ((s = xf86GetOptValString(pTrident->Options, OPTION_GB))) {
1259	int brightness = -1;
1260	double gamma = -1.0;
1261	Bool error = FALSE;
1262	int i;
1263
1264	i = sscanf(s,"%lf %i",&gamma,&brightness);
1265
1266	if (i != 2 || brightness == -1 || gamma == -1.0) {
1267	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1268		       "Invalid Gamma/Brightness argument: %s\n",s);
1269	    error = TRUE;
1270	} else {
1271	    if (brightness < 0 || brightness > 128) {
1272		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1273			   "brightness out of range [0,128]: %i\n",brightness);
1274		error = TRUE;
1275	    }
1276	    if (gamma <= 0.0 || gamma > 10.0) {
1277		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1278			   "gamma out of range (0,10.0]: %f\n",gamma);
1279		error = TRUE;
1280	    }
1281	}
1282
1283	if (!error) {
1284	    pTrident->GammaBrightnessOn = TRUE;
1285	    pTrident->gamma = gamma;
1286	    pTrident->brightness = brightness;
1287	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Gamma: %f Brightness: %i\n",
1288		       gamma,brightness);
1289	}
1290    }
1291
1292    /* The following is a temporary hack */
1293    pTrident->FPDelay = 7; /* invalid value */
1294    if (xf86GetOptValInteger(pTrident->Options, OPTION_FP_DELAY,
1295			     &pTrident->FPDelay)) {
1296	if (pTrident->FPDelay < -2 || pTrident->FPDelay > 5) {
1297	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FPDelay %i out if range "
1298		       "(-2 < FPDelay < 5)\n",pTrident->FPDelay);
1299	    pTrident->FPDelay = 7;
1300	} else
1301	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP Delay set to %i\n",
1302		   pTrident->FPDelay);
1303    }
1304    if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_SHADOW, FALSE)) {
1305	pTrident->CyberShadow = TRUE;
1306	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Shadow enabled\n");
1307    }
1308    if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_STRETCH, FALSE)) {
1309	pTrident->CyberStretch = TRUE;
1310	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Stretch enabled\n");
1311    }
1312
1313    pTrident->MUXThreshold = 90000; /* 90MHz */
1314    if (xf86GetOptValInteger(pTrident->Options, OPTION_MUX_THRESHOLD,
1315						&pTrident->MUXThreshold)) {
1316	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MUX Threshold set to %d\n",
1317						pTrident->MUXThreshold);
1318    }
1319    pTrident->OverrideHsync = 0;
1320    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC,
1321						&pTrident->OverrideHsync)) {
1322	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n",
1323						pTrident->OverrideHsync);
1324    }
1325    pTrident->OverrideVsync = 0;
1326    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC,
1327						&pTrident->OverrideVsync)) {
1328	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n",
1329						pTrident->OverrideVsync);
1330    }
1331    pTrident->OverrideHsync = 0;
1332    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC,
1333						&pTrident->OverrideHsync)) {
1334	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n",
1335						pTrident->OverrideHsync);
1336    }
1337    pTrident->OverrideVsync = 0;
1338    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC,
1339						&pTrident->OverrideVsync)) {
1340	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n",
1341						pTrident->OverrideVsync);
1342    }
1343    pTrident->OverrideRskew = 0;
1344    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_RSKEW,
1345						&pTrident->OverrideRskew)) {
1346	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Rskew set to %d\n",
1347						pTrident->OverrideRskew);
1348    }
1349    pTrident->OverrideBskew = 0;
1350    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_BSKEW,
1351						&pTrident->OverrideBskew)) {
1352	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Bskew set to %d\n",
1353						pTrident->OverrideBskew);
1354    }
1355    if (xf86ReturnOptValBool(pTrident->Options, OPTION_SHADOW_FB, FALSE)) {
1356        if (!pTrident->Linear)
1357	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option SHADOW_FB"
1358		       " in non-Linear Mode\n");
1359	else {
1360	    pTrident->ShadowFB = TRUE;
1361	    pTrident->NoAccel = TRUE;
1362	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1363		    "Using \"Shadow Framebuffer\" - acceleration disabled\n");
1364	}
1365    }
1366    pTrident->Rotate = 0;
1367    if ((s = xf86GetOptValString(pTrident->Options, OPTION_ROTATE))) {
1368        if (!pTrident->Linear)
1369	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option ROTATE "
1370		       "in non-Linear Mode\n");
1371	else {
1372	    if(!xf86NameCmp(s, "CW")) {
1373	        /* accel is disabled below for shadowFB */
1374	        pTrident->ShadowFB = TRUE;
1375		pTrident->NoAccel = TRUE;
1376		pTrident->HWCursor = FALSE;
1377		pTrident->Rotate = 1;
1378		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
1379		       "Rotating screen clockwise - acceleration disabled\n");
1380	    } else if(!xf86NameCmp(s, "CCW")) {
1381 	        pTrident->ShadowFB = TRUE;
1382		pTrident->NoAccel = TRUE;
1383		pTrident->HWCursor = FALSE;
1384		pTrident->Rotate = -1;
1385		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
1386			   "counter clockwise - acceleration disabled\n");
1387	    } else {
1388	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
1389			   "value for Option \"Rotate\"\n", s);
1390		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1391			   "Valid options are \"CW\" or \"CCW\"\n");
1392	    }
1393	}
1394    }
1395
1396    pTrident->TVChipset = 0;
1397    if ((s = xf86GetOptValString(pTrident->Options, OPTION_TV_CHIPSET))) {
1398	if(!xf86NameCmp(s, "VT1621")) {
1399	    pTrident->TVChipset = 1;
1400	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Using VIA VT1621 TV chip\n");
1401	} else if (!xf86NameCmp(s, "CH7005")) {
1402	    pTrident->TVChipset = 2;
1403	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Using Chrontel CH7005 TV chip\n");
1404	} else
1405	    xf86DrvMsg(pScrn->scrnIndex,X_ERROR,
1406		       "%s is an unknown TV chipset option\n",s);
1407    }
1408    /* Default : NTSC */
1409    pTrident->TVSignalMode=0;
1410    if (xf86GetOptValInteger(pTrident->Options, OPTION_TV_SIGNALMODE,
1411						&pTrident->TVSignalMode)) {
1412	ErrorF("TV SignalMode set to %d\n",pTrident->TVSignalMode);
1413    }
1414
1415    /* FIXME ACCELERATION */
1416    if (!UseMMIO) pTrident->NoAccel = TRUE;
1417
1418    if (pTrident->Linear) {
1419    	if (pTrident->pEnt->device->MemBase != 0) {
1420	    /*
1421	     * XXX Should check that the config file value matches one of the
1422	     * PCI base address values.
1423	     */
1424	    pTrident->FbAddress = pTrident->pEnt->device->MemBase;
1425	    from = X_CONFIG;
1426    	} else {
1427    	    if (IsPciCard)
1428	    	pTrident->FbAddress = PCI_REGION_BASE(pTrident->PciInfo, 0, REGION_MEM) & 0xFFFFFFF0;
1429	    else
1430	    	pTrident->FbAddress = 0xA0000;
1431    	}
1432
1433    	xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
1434	       (unsigned long)pTrident->FbAddress);
1435    }
1436
1437    if (UseMMIO) {
1438    	if (pTrident->pEnt->device->IOBase != 0) {
1439	    /*
1440	     * XXX Should check that the config file value matches one of the
1441	     * PCI base address values.
1442	     */
1443	    pTrident->IOAddress = pTrident->pEnt->device->IOBase;
1444	    from = X_CONFIG;
1445    	} else {
1446    	    if (IsPciCard)
1447	    	pTrident->IOAddress = PCI_REGION_BASE(pTrident->PciInfo, 1, REGION_MEM) & 0xFFFFC000;
1448	    else
1449	    	/* FIXME - Multihead UNAWARE */
1450    	    	pTrident->IOAddress = 0xBF000;
1451    	}
1452
1453    	xf86DrvMsg(pScrn->scrnIndex,X_PROBED,"IO registers at 0x%lX\n",
1454		   (unsigned long)pTrident->IOAddress);
1455    }
1456
1457#ifndef XSERVER_LIBPCIACCESS
1458    /* Register the PCI-assigned resources. */
1459    if (xf86RegisterResources(pTrident->pEnt->index, NULL, ResExclusive)) {
1460	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1461		   "xf86RegisterResources() found resource conflicts\n");
1462	return FALSE;
1463    }
1464#endif
1465    /* Initialize VBE if possible
1466     * Don't move this past MMIO enable!!
1467     * PIO access will be blocked
1468     * when MMIO is turned on!
1469     */
1470
1471    if (xf86LoadSubModule(pScrn, "vbe")) {
1472	vbeInfoPtr pVbe;
1473
1474	pVbe =  VBEInit(NULL,pTrident->pEnt->index);
1475	pMon = vbeDoEDID(pVbe, NULL);
1476#ifdef VBE_INFO
1477	{
1478	    VbeInfoBlock* vbeInfoBlockPtr;
1479	    if ((vbeInfoBlockPtr = VBEGetVBEInfo(pVbe))) {
1480		pTrident->vbeModes = VBEBuildVbeModeList(pVbe,vbeInfoBlockPtr);
1481		VBEFreeVBEInfo(vbeInfoBlockPtr);
1482	    }
1483	}
1484#endif
1485	vbeFree(pVbe);
1486	if (pMon) {
1487	    if (!xf86LoadSubModule(pScrn, "ddc")) {
1488		TRIDENTFreeRec(pScrn);
1489		return FALSE;
1490	    } else {
1491		xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon));
1492		ddcLoaded = TRUE;
1493	    }
1494	}
1495
1496    }
1497
1498    if (xf86GetOptValBool(pTrident->Options, OPTION_1400_DISPLAY, &tmp_bool)) {
1499	if (tmp_bool)
1500	    pTrident->displaySize = 1400;
1501    } else
1502	pTrident->displaySize = TRIDENTLcdDisplaySize(pMon);
1503
1504    if (IsPciCard && UseMMIO) {
1505    	if (!TRIDENTMapMem(pScrn))
1506	    return FALSE;
1507
1508    	TRIDENTEnableMMIO(pScrn);
1509    }
1510
1511    OUTB(0x3C4, RevisionID); revision = INB(0x3C5);
1512    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Revision is %d\n",revision);
1513
1514    pScrn->progClock = TRUE;
1515    pTrident->EngineOperation = 0x00;
1516    pTrident->IsCyber = FALSE;
1517    pTrident->HasSGRAM = FALSE;
1518    pTrident->NewClockCode = FALSE;
1519    pTrident->MUX = FALSE;
1520    Support24bpp = FALSE;
1521
1522    OUTB(vgaIOBase + 4, InterfaceSel);
1523
1524    switch (pTrident->Chipset) {
1525	case TVGA9000:
1526	case TVGA9000i:
1527	    pScrn->progClock = FALSE;
1528	    NoClocks = 16;
1529	    pTrident->NoMMIO = TRUE;
1530	    pTrident->NoAccel = TRUE;
1531	    pTrident->HWCursor = FALSE;
1532	    chipset = "TVGA9000/9000i";
1533	    ramtype = "Standard DRAM";
1534	    if (pTrident->UsePCIRetry)
1535	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1536	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1537	    pTrident->frequency = NTSC;
1538	    break;
1539	case TVGA9100B:
1540	    pScrn->progClock = FALSE;
1541	    NoClocks = 8;
1542	    pTrident->NoMMIO = TRUE;
1543	    pTrident->NoAccel = TRUE;
1544	    pTrident->HWCursor = FALSE;
1545	    chipset = "TVGA9100B";
1546	    ramtype = "Standard DRAM";
1547	    if (pTrident->UsePCIRetry)
1548	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1549	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1550	    pTrident->frequency = NTSC;
1551	    break;
1552	case TVGA8900B:
1553	    pScrn->progClock = FALSE;
1554	    NoClocks = 8;
1555	    pTrident->NoMMIO = TRUE;
1556	    pTrident->NoAccel = TRUE;
1557	    pTrident->HWCursor = FALSE;
1558	    chipset = "TVGA8900B";
1559	    ramtype = "Standard DRAM";
1560	    if (pTrident->UsePCIRetry)
1561	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1562	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1563	    pTrident->frequency = NTSC;
1564	    break;
1565	case TVGA8900C:
1566	    pScrn->progClock = FALSE;
1567	    NoClocks = 16;
1568	    pTrident->NoMMIO = TRUE;
1569	    pTrident->NoAccel = TRUE;
1570	    pTrident->HWCursor = FALSE;
1571	    chipset = "TVGA8900C";
1572	    ramtype = "Standard DRAM";
1573	    if (pTrident->UsePCIRetry)
1574	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1575	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1576	    pTrident->frequency = NTSC;
1577	    break;
1578	case TVGA8900D:
1579	    pScrn->progClock = FALSE;
1580	    NoClocks = 16;
1581	    pTrident->NoMMIO = TRUE;
1582	    pTrident->NoAccel = TRUE;
1583	    pTrident->HWCursor = FALSE;
1584	    chipset = "TVGA8900D";
1585	    ramtype = "Standard DRAM";
1586	    if (pTrident->UsePCIRetry)
1587	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1588	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1589	    pTrident->frequency = NTSC;
1590	    break;
1591	case TVGA9200CXr:
1592	    pScrn->progClock = FALSE;
1593	    NoClocks = 16;
1594	    pTrident->NoMMIO = TRUE;
1595	    pTrident->NoAccel = TRUE;
1596	    pTrident->HWCursor = FALSE;
1597	    chipset = "TVGA9200CXr";
1598	    ramtype = "Standard DRAM";
1599	    if (pTrident->UsePCIRetry)
1600	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1601	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1602	    pTrident->frequency = NTSC;
1603	    break;
1604	case TGUI9400CXi:
1605	    pScrn->progClock = FALSE;
1606	    NoClocks = 16;
1607	    pTrident->NoMMIO = TRUE;
1608	    pTrident->NoAccel = TRUE;
1609	    pTrident->HWCursor = FALSE;
1610	    chipset = "TVGA9200CXr";
1611	    ramtype = "Standard DRAM";
1612	    if (pTrident->UsePCIRetry)
1613	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1614	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1615	    pTrident->frequency = NTSC;
1616	    break;
1617	case TGUI9440AGi:
1618    	    pTrident->ddc1Read = Tridentddc1Read;
1619	    pTrident->HWCursor = FALSE;
1620	    chipset = "TGUI9440AGi";
1621	    ramtype = "Standard DRAM";
1622	    if (pTrident->UsePCIRetry)
1623	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1624	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1625	    pTrident->frequency = NTSC;
1626	    break;
1627	case CYBER9320:
1628    	    pTrident->ddc1Read = Tridentddc1Read;
1629	    chipset = "Cyber9320";
1630	    ramtype = "Standard DRAM";
1631	    if (pTrident->UsePCIRetry)
1632	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1633	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1634	    break;
1635	/* Trident didn't update the PCI ID's and so we have to detemine
1636	 * which chips are right ! Then override pTrident->Chipset to
1637	 * correct values */
1638	case TGUI9660:
1639    	    pTrident->ddc1Read = Tridentddc1Read;
1640    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1641		ramtype = "EDO Ram";
1642    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C)
1643		ramtype = "Standard DRAM";
1644	    switch (revision) {
1645		case 0x00:
1646		    chipset = "TGUI9660";
1647		    pTrident->Chipset = TGUI9660;
1648		    if (pTrident->UsePCIRetry)
1649		    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1650		    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1651		    break;
1652		case 0x01:
1653		    chipset = "TGUI9680";
1654		    pTrident->Chipset = TGUI9680;
1655		    if (pTrident->UsePCIRetry)
1656		    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
1657		    pTrident->UsePCIRetry = FALSE; /* Not Supported */
1658		    break;
1659		case 0x10:
1660		    chipset = "ProVidia 9682";
1661		    Support24bpp = TRUE;
1662		    pTrident->Chipset = PROVIDIA9682;
1663		    break;
1664		case 0x21:
1665		    chipset = "ProVidia 9685";
1666		    Support24bpp = TRUE;
1667		    pTrident->NewClockCode = TRUE;
1668		    pTrident->Chipset = PROVIDIA9685;
1669		    break;
1670		case 0x22:
1671		case 0x23:
1672		    chipset = "Cyber 9397";
1673    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1674			ramtype = "EDO Ram";
1675    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1676			ramtype = "SDRAM";
1677    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1678			pTrident->HasSGRAM = TRUE;
1679			ramtype = "SGRAM";
1680	    	    }
1681		    pTrident->NewClockCode = TRUE;
1682		    pTrident->Chipset = CYBER9397;
1683		    pTrident->IsCyber = TRUE;
1684		    break;
1685		case 0x2a:
1686		    chipset = "Cyber 9397/DVD";
1687    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1688			ramtype = "EDO Ram";
1689    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1690			ramtype = "SDRAM";
1691    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1692			pTrident->HasSGRAM = TRUE;
1693			ramtype = "SGRAM";
1694	    	    }
1695		    pTrident->NewClockCode = TRUE;
1696		    pTrident->Chipset = CYBER9397DVD;
1697		    pTrident->IsCyber = TRUE;
1698		    break;
1699		case 0x30:
1700		case 0x33:
1701		case 0x34:
1702		case 0x35:
1703		case 0xB3:
1704		    chipset = "Cyber 9385";
1705		    pTrident->NewClockCode = TRUE;
1706		    pTrident->Chipset = CYBER9385;
1707		    pTrident->IsCyber = TRUE;
1708		    break;
1709		case 0x38:
1710		case 0x3A:
1711		    chipset = "Cyber 9385-1";
1712		    pTrident->NewClockCode = TRUE;
1713		    pTrident->Chipset = CYBER9385;
1714		    pTrident->IsCyber = TRUE;
1715		    break;
1716		case 0x40:
1717		case 0x41:
1718		case 0x42:
1719		case 0x43:
1720		    chipset = "Cyber 9382";
1721		    pTrident->NewClockCode = TRUE;
1722		    pTrident->Chipset = CYBER9382;
1723		    pTrident->IsCyber = TRUE;
1724		    break;
1725		case 0x4A:
1726		    chipset = "Cyber 9388";
1727    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1728			ramtype = "EDO Ram";
1729    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1730			ramtype = "SDRAM";
1731    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1732			pTrident->HasSGRAM = TRUE;
1733			ramtype = "SGRAM";
1734	    	    }
1735		    pTrident->NewClockCode = TRUE;
1736		    pTrident->Chipset = CYBER9388;
1737		    pTrident->IsCyber = TRUE;
1738		    break;
1739		default:
1740		    chipset = "Unknown";
1741		    pTrident->Chipset = TGUI9660;
1742		    break;
1743	    }
1744	    break;
1745	case CYBER9388:
1746    	    pTrident->ddc1Read = Tridentddc1Read;
1747    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1748		ramtype = "EDO Ram";
1749    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1750		ramtype = "SDRAM";
1751    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1752		pTrident->HasSGRAM = TRUE;
1753		ramtype = "SGRAM";
1754	    }
1755	    pTrident->IsCyber = TRUE;
1756	    Support24bpp = TRUE;
1757	    chipset = "Cyber 9388";
1758	    pTrident->NewClockCode = TRUE;
1759	    break;
1760	case CYBER9397:
1761    	    pTrident->ddc1Read = Tridentddc1Read;
1762    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1763		ramtype = "EDO Ram";
1764    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1765		ramtype = "SDRAM";
1766    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1767		pTrident->HasSGRAM = TRUE;
1768		ramtype = "SGRAM";
1769	    }
1770	    pTrident->IsCyber = TRUE;
1771	    Support24bpp = TRUE;
1772	    chipset = "Cyber 9397";
1773	    pTrident->NewClockCode = TRUE;
1774	    break;
1775	case CYBER9397DVD:
1776    	    pTrident->ddc1Read = Tridentddc1Read;
1777    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1778		ramtype = "EDO Ram";
1779    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1780		ramtype = "SDRAM";
1781    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1782		pTrident->HasSGRAM = TRUE;
1783		ramtype = "SGRAM";
1784	    }
1785	    pTrident->IsCyber = TRUE;
1786	    Support24bpp = TRUE;
1787	    chipset = "Cyber 9397/DVD";
1788	    pTrident->NewClockCode = TRUE;
1789	    break;
1790	case CYBER9520:
1791    	    pTrident->ddc1Read = Tridentddc1Read;
1792    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1793		ramtype = "EDO Ram";
1794    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1795		ramtype = "SDRAM";
1796    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1797		pTrident->HasSGRAM = TRUE;
1798		ramtype = "SGRAM";
1799	    }
1800	    pTrident->IsCyber = TRUE;
1801	    Support24bpp = TRUE;
1802	    chipset = "Cyber 9520";
1803	    pTrident->NewClockCode = TRUE;
1804	    break;
1805	case CYBER9525DVD:
1806    	    pTrident->ddc1Read = Tridentddc1Read;
1807    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1808		ramtype = "EDO Ram";
1809    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1810		ramtype = "SDRAM";
1811    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1812		pTrident->HasSGRAM = TRUE;
1813		ramtype = "SGRAM";
1814	    }
1815	    pTrident->IsCyber = TRUE;
1816	    Support24bpp = TRUE;
1817	    chipset = "Cyber 9525/DVD";
1818	    pTrident->NewClockCode = TRUE;
1819	    break;
1820	case CYBERBLADEE4:
1821    	    pTrident->ddc1Read = Tridentddc1Read;
1822	    ramtype = "SDRAM";
1823	    pTrident->IsCyber = TRUE;
1824	    Support24bpp = TRUE;
1825	    chipset = "CyberBlade e4/128";
1826	    pTrident->NewClockCode = TRUE;
1827	    break;
1828	case IMAGE975:
1829    	    pTrident->ddc1Read = Tridentddc1Read;
1830    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1831		ramtype = "EDO Ram";
1832    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1833		ramtype = "SDRAM";
1834    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1835		pTrident->HasSGRAM = TRUE;
1836		ramtype = "SGRAM";
1837	    }
1838	    Support24bpp = TRUE;
1839	    chipset = "3DImage975";
1840	    pTrident->NewClockCode = TRUE;
1841	    break;
1842	case IMAGE985:
1843    	    pTrident->ddc1Read = Tridentddc1Read;
1844    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
1845		ramtype = "EDO Ram";
1846    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1847		ramtype = "SDRAM";
1848    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1849		pTrident->HasSGRAM = TRUE;
1850		ramtype = "SGRAM";
1851	    }
1852	    Support24bpp = TRUE;
1853	    chipset = "3DImage985";
1854	    pTrident->NewClockCode = TRUE;
1855	    break;
1856	case BLADE3D:
1857    	    pTrident->ddc1Read = Tridentddc1Read;
1858    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
1859		ramtype = "SDRAM";
1860    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
1861		pTrident->HasSGRAM = TRUE;
1862		ramtype = "SGRAM";
1863	    }
1864	    Support24bpp = TRUE;
1865	    chipset = "Blade3D";
1866	    pTrident->NewClockCode = TRUE;
1867	    pTrident->frequency = NTSC;
1868	    pTrident->UsePCIRetry = TRUE; /* To avoid lockups */
1869	    break;
1870	case CYBERBLADEI7:
1871    	    pTrident->ddc1Read = Tridentddc1Read;
1872	    ramtype = "SDRAM";
1873	    /* pTrident->IsCyber = TRUE; VIA MVP4 integrated Desktop version */
1874	    Support24bpp = TRUE;
1875	    chipset = "CyberBlade/i7/VIA MVP4";
1876	    pTrident->NewClockCode = TRUE;
1877	    pTrident->frequency = NTSC;
1878	    break;
1879	case CYBERBLADEI7D:
1880    	    pTrident->ddc1Read = Tridentddc1Read;
1881	    ramtype = "SDRAM";
1882	    pTrident->IsCyber = TRUE;
1883	    Support24bpp = TRUE;
1884	    chipset = "CyberBlade/DSTN/i7";
1885	    pTrident->NewClockCode = TRUE;
1886	    pTrident->frequency = NTSC;
1887	    break;
1888	case CYBERBLADEI1:
1889    	    pTrident->ddc1Read = Tridentddc1Read;
1890	    ramtype = "SDRAM";
1891	    pTrident->IsCyber = TRUE;
1892	    Support24bpp = TRUE;
1893	    chipset = "CyberBlade/i1";
1894	    pTrident->NewClockCode = TRUE;
1895	    pTrident->frequency = NTSC;
1896	    break;
1897	case CYBERBLADEI1D:
1898    	    pTrident->ddc1Read = Tridentddc1Read;
1899	    ramtype = "SDRAM";
1900	    pTrident->IsCyber = TRUE;
1901	    Support24bpp = TRUE;
1902	    chipset = "CyberBlade/DSTN/i1";
1903	    pTrident->NewClockCode = TRUE;
1904	    pTrident->frequency = NTSC;
1905	    break;
1906	case CYBERBLADEAI1:
1907    	    pTrident->ddc1Read = Tridentddc1Read;
1908	    ramtype = "SDRAM";
1909	    pTrident->IsCyber = TRUE;
1910	    Support24bpp = TRUE;
1911	    chipset = "CyberBlade/Ai1";
1912	    pTrident->NewClockCode = TRUE;
1913	    pTrident->frequency = NTSC;
1914	    break;
1915	case CYBERBLADEAI1D:
1916    	    pTrident->ddc1Read = Tridentddc1Read;
1917	    ramtype = "SDRAM";
1918	    pTrident->IsCyber = TRUE;
1919	    Support24bpp = TRUE;
1920	    chipset = "CyberBlade/DSTN/Ai1";
1921	    pTrident->NewClockCode = TRUE;
1922	    pTrident->frequency = NTSC;
1923	    break;
1924	case BLADEXP: /* 0x9910 */
1925	    pTrident->ddc1Read = Tridentddc1Read;
1926	    ramtype = "SGRAM";
1927	    pTrident->HasSGRAM = TRUE;
1928	    Support24bpp = TRUE;
1929	    pTrident->NewClockCode = TRUE;
1930	    pTrident->frequency = NTSC;
1931	    OUTB(0x3C4, 0x5D);
1932	    if (PCI_SUB_VENDOR_ID(pTrident->PciInfo) != 0x1023) {
1933	    	chipset = "CyberBladeXP";
1934	    	pTrident->IsCyber = TRUE;
1935	    } else
1936	    if (!(INB(0x3C5) & 0x01)) {
1937	    	chipset = "BladeXP";
1938	    } else {
1939		CARD8 mem1, mem2;
1940		OUTB(vgaIOBase + 0x04, SPR);
1941		mem1 = INB(vgaIOBase + 5);
1942		OUTB(vgaIOBase + 0x04, 0xC1);
1943		mem2 = INB(vgaIOBase + 5);
1944		if ((mem1 & 0x0e) && (mem2 == 0x11)) {
1945	    	    chipset = "BladeT64";
1946		} else {
1947	    	    chipset = "BladeT16";
1948		}
1949	    }
1950	    break;
1951	case CYBERBLADEXPAI1:
1952    	    pTrident->ddc1Read = Tridentddc1Read;
1953	    ramtype = "SGRAM";
1954            pTrident->HasSGRAM = TRUE;
1955	    pTrident->IsCyber = TRUE;
1956	    pTrident->shadowNew = TRUE;
1957	    Support24bpp = TRUE;
1958	    chipset = "CyberBladeXPAi1";
1959	    pTrident->NewClockCode = TRUE;
1960	    pTrident->frequency = NTSC;
1961	    break;
1962	case CYBERBLADEXP4:
1963    	    pTrident->ddc1Read = Tridentddc1Read;
1964	    ramtype = "SGRAM";
1965            pTrident->HasSGRAM = TRUE;
1966	    pTrident->IsCyber = TRUE;
1967	    pTrident->shadowNew = TRUE;
1968	    Support24bpp = TRUE;
1969	    chipset = "CyberBladeXP4";
1970	    pTrident->NewClockCode = TRUE;
1971	    pTrident->frequency = NTSC;
1972	    break;
1973	case XP5:
1974    	    pTrident->ddc1Read = Tridentddc1Read;
1975	    ramtype = "SGRAM";
1976            pTrident->HasSGRAM = TRUE;
1977	    pTrident->IsCyber = TRUE;
1978	    pTrident->shadowNew = TRUE;
1979	    Support24bpp = TRUE;
1980	    chipset = "XP5";
1981	    pTrident->NewClockCode = TRUE;
1982	    pTrident->frequency = NTSC;
1983	    break;
1984    }
1985
1986    if (!pScrn->progClock) {
1987	pScrn->numClocks = NoClocks;
1988	xf86GetClocks(pScrn, NoClocks, TRIDENTClockSelect,
1989			  vgaHWProtectWeak(),
1990			  vgaHWBlankScreenWeak(),
1991			  vgaIOBase + 0x0A, 0x08, 1, 28322);
1992	from = X_PROBED;
1993	xf86ShowClocks(pScrn, from);
1994    }
1995
1996    if (!chipset) {
1997	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No support for \"%s\"\n",
1998			pScrn->chipset);
1999	if (IsPciCard && UseMMIO) {
2000    	    TRIDENTDisableMMIO(pScrn);
2001 	    TRIDENTUnmapMem(pScrn);
2002	}
2003	return FALSE;
2004    }
2005    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Found %s chip\n", chipset);
2006    if (ramtype)
2007	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RAM type is %s\n", ramtype);
2008
2009    if (pScrn->bitsPerPixel == 24 && !Support24bpp) {
2010	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No support for 24bpp on this chipset, use -pixmap32.\n");
2011	if (IsPciCard && UseMMIO) {
2012    	    TRIDENTDisableMMIO(pScrn);
2013 	    TRIDENTUnmapMem(pScrn);
2014	}
2015	return FALSE;
2016    }
2017
2018    /* HW bpp matches reported bpp */
2019    pTrident->HwBpp = pScrn->bitsPerPixel;
2020
2021    /* Due to bugs in the chip, turn it off */
2022    if (pTrident->Chipset >= CYBERBLADEI7 && pTrident->Chipset <= CYBERBLADEAI1D)
2023	pTrident->HWCursor = FALSE;
2024
2025    from = X_PROBED;
2026    if (pTrident->pEnt->device->videoRam != 0) {
2027	pScrn->videoRam = pTrident->pEnt->device->videoRam;
2028	from = X_CONFIG;
2029    } else {
2030      if (pTrident->Chipset == XP5) {
2031	OUTB(vgaIOBase + 4, 0x60);
2032	videoram = INB(vgaIOBase + 5);
2033	switch (videoram & 0x7) {
2034 	case 0x00:
2035	    pScrn->videoRam = 65536 /* 131072 */;
2036	    break;
2037	case 0x01:
2038	    pScrn->videoRam = 65536;
2039	    break;
2040	case 0x02:
2041	    pScrn->videoRam = 32768;
2042	    break;
2043	case 0x03:
2044	    pScrn->videoRam = 16384;
2045	    break;
2046	case 0x04:
2047	    pScrn->videoRam = 8192;
2048	    break;
2049	}
2050      } else
2051      if (pTrident->Chipset == CYBER9525DVD) {
2052	pScrn->videoRam = 2560;
2053      } else
2054      {
2055	OUTB(vgaIOBase + 4, SPR);
2056	videoram = INB(vgaIOBase + 5);
2057	if (pTrident->Chipset < TGUI9440AGi)
2058	    videorammask = 0x07;
2059	else
2060	    videorammask = 0x0F;
2061	switch (videoram & videorammask) {
2062  	case 0x01:
2063  	    pScrn->videoRam = 512;
2064  	    break;
2065 	case 0x02: /* XP */
2066 	    pScrn->videoRam = 6144;
2067 	    break;
2068  	case 0x03:
2069  	    pScrn->videoRam = 1024;
2070  	    break;
2071	case 0x04:
2072	    pScrn->videoRam = 8192;
2073	    break;
2074 	case 0x06: /* XP */
2075 	    pScrn->videoRam = 10240;
2076 	    break;
2077  	case 0x07:
2078  	    pScrn->videoRam = 2048;
2079  	    break;
2080 	case 0x08: /* XP */
2081 	    pScrn->videoRam = 12288;
2082 	    break;
2083 	case 0x0A: /* XP */
2084 	    pScrn->videoRam = 14336;
2085 	    break;
2086 	case 0x0C: /* XP */
2087 	    pScrn->videoRam = 16384;
2088 	    break;
2089 	case 0x0E: /* XP */
2090 	    OUTB(vgaIOBase + 4, 0xC1);
2091 	    switch (INB(vgaIOBase + 5) & 0x11) {
2092 		case 0x00:
2093 		    pScrn->videoRam = 20480;
2094 		    break;
2095 		case 0x01:
2096 		    pScrn->videoRam = 24576;
2097 		    break;
2098 		case 0x10:
2099 		    pScrn->videoRam = 28672;
2100 		    break;
2101 		case 0x11:
2102 		    pScrn->videoRam = 32768;
2103 		    break;
2104 	    }
2105 	    break;
2106 	case 0x0F:
2107  	    pScrn->videoRam = 4096;
2108  	    break;
2109	default:
2110	    pScrn->videoRam = 1024;
2111	    xf86DrvMsg(pScrn->scrnIndex, from,
2112			"Unable to determine VideoRam, defaulting to 1MB\n");
2113	    break;
2114	}
2115      }
2116    }
2117
2118    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
2119		pTrident->HWCursor ? "HW" : "SW");
2120
2121    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
2122               pScrn->videoRam);
2123
2124    if (pTrident->IsCyber) {
2125	unsigned char mod, dsp, dsp1;
2126
2127	pTrident->lcdMode = 0xff;
2128
2129	OUTB(0x3CE,0x42);
2130	dsp = INB(0x3CF);
2131	OUTB(0x3CE,0x43);
2132	dsp1 = INB(0x3CF);
2133	OUTB(0x3CE,0x52);
2134	mod = INB(0x3CF);
2135	/*
2136	 * Only allow display size override if 1280x1024 is detected
2137	 * Currently 1400x1050 is supported - which is detected as
2138	 * 1280x1024
2139	 */
2140	if (pTrident->displaySize) {
2141	    if (((mod >> 4) & 3) == 0) {
2142		for (i = 0; LCD[i].mode != 0xff; i++) {
2143		    if (pTrident->displaySize == LCD[i].display_x)
2144			pTrident->lcdMode = LCD[i].mode;
2145		}
2146		xf86DrvMsg(pScrn->scrnIndex,
2147			   X_INFO,"%s Panel %ix%i found\n",
2148			   (dsp & 0x80) ? "TFT" :
2149			   ((dsp1 & 0x20) ? "DSTN" : "STN"),
2150			   LCD[i].display_x,LCD[i].display_y);
2151	    } else {
2152		xf86DrvMsg(pScrn->scrnIndex,X_WARNING,
2153			   "Display size override only for 1280x1024\n");
2154		pTrident->displaySize = 0;
2155	    }
2156	}
2157
2158	if (!pTrident->displaySize) {
2159	    for (i = 0; LCD[i].mode != 0xff; i++) {
2160		if (LCD[i].mode == ((mod >> 4) & 3)) {
2161		    pTrident->lcdMode = i;
2162		    xf86DrvMsg(pScrn->scrnIndex,
2163			       X_PROBED,"%s Panel %ix%i found\n",
2164			       (dsp & 0x80) ? "TFT" :
2165			       ((dsp1 & 0x20) ? "DSTN" : "STN"),
2166			       LCD[i].display_x,LCD[i].display_y);
2167		}
2168	    }
2169	}
2170	if (pTrident->dspOverride) {
2171	    if (pTrident->dspOverride & LCD_ACTIVE)
2172		pTrident->lcdActive = TRUE;
2173	    else
2174		pTrident->lcdActive = FALSE;
2175	} else {
2176	    OUTB(0x3CE, FPConfig);
2177	    pTrident->lcdActive = (INB(0x3CF) & 0x10);
2178	}
2179    }
2180
2181    pTrident->MCLK = 0;
2182    mclk = CalculateMCLK(pScrn);
2183    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Memory Clock is %3.2f MHz\n", mclk);
2184    if (xf86GetOptValFreq(pTrident->Options, OPTION_SETMCLK, OPTUNITS_MHZ,
2185				&real)) {
2186	pTrident->MCLK = (int)(real * 1000.0);
2187	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting new Memory Clock to %3.2f MHz\n",
2188						(float)(pTrident->MCLK / 1000));
2189    }
2190
2191    /* Set the min pixel clock */
2192    pTrident->MinClock = 12000;	/* XXX Guess, need to check this */
2193    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
2194	       pTrident->MinClock / 1000);
2195
2196    /*
2197     * If the user has specified ramdac speed in the XF86Config
2198     * file, we respect that setting.
2199     */
2200    if (pTrident->pEnt->device->dacSpeeds[0]) {
2201	int speed = 0;
2202
2203	switch (pScrn->bitsPerPixel) {
2204	case 8:
2205	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP8];
2206	   break;
2207	case 16:
2208	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP16];
2209	   break;
2210	case 24:
2211	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP24];
2212	   break;
2213	case 32:
2214	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP32];
2215	   break;
2216	}
2217	if (speed == 0)
2218	    pTrident->MaxClock = pTrident->pEnt->device->dacSpeeds[0];
2219	else
2220	    pTrident->MaxClock = speed;
2221	from = X_CONFIG;
2222    } else {
2223	switch (pScrn->bitsPerPixel) {
2224	    case 16:
2225		pTrident->MaxClock = ClockLimit16bpp[pTrident->Chipset];
2226		break;
2227	    case 24:
2228		pTrident->MaxClock = ClockLimit24bpp[pTrident->Chipset];
2229		break;
2230	    case 32:
2231		pTrident->MaxClock = ClockLimit32bpp[pTrident->Chipset];
2232		break;
2233	    default:
2234		pTrident->MaxClock = ClockLimit[pTrident->Chipset];
2235		break;
2236	}
2237    }
2238    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
2239	       pTrident->MaxClock / 1000);
2240
2241    /*
2242     * Setup the ClockRanges, which describe what clock ranges are available,
2243     * and what sort of modes they can be used for.
2244     */
2245    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
2246    clockRanges->next = NULL;
2247    if (!pScrn->progClock) {
2248	if (pScrn->videoRam < 1024)
2249    	    clockRanges->ClockMulFactor = 2;
2250	if (pScrn->bitsPerPixel == 16)
2251    	    clockRanges->ClockMulFactor = 2;
2252    }
2253    clockRanges->minClock = pTrident->MinClock;
2254    clockRanges->maxClock = pTrident->MaxClock;
2255    clockRanges->clockIndex = -1;		/* programmable */
2256    clockRanges->interlaceAllowed = TRUE;
2257    clockRanges->doubleScanAllowed = TRUE;
2258
2259    /*
2260     * xf86ValidateModes will check that the mode HTotal and VTotal values
2261     * don't exceed the chipset's limit if pScrn->maxHValue and
2262     * pScrn->maxVValue are set.  Since our TRIDENTValidMode() already takes
2263     * care of this, we don't worry about setting them here.
2264     */
2265
2266    if (pScrn->bitsPerPixel == 24) {
2267    	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
2268		"Disabling Engine due to 24bpp.\n");
2269	    pTrident->NoAccel = TRUE;
2270    }
2271
2272    /* Select valid modes from those available */
2273    if (pTrident->NoAccel || Is3Dchip) {
2274	/*
2275	 * XXX Assuming min pitch 256, max 4096
2276	 * XXX Assuming min height 128, max 4096
2277	 */
2278	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2279			      pScrn->display->modes, clockRanges,
2280			      NULL, 256, 4096,
2281			      pScrn->bitsPerPixel, 128, 4096,
2282			      pScrn->display->virtualX,
2283			      pScrn->display->virtualY,
2284			      pTrident->FbMapSize,
2285			      LOOKUP_BEST_REFRESH);
2286    } else {
2287	/*
2288	 * XXX Assuming min height 128, max 2048
2289	 */
2290	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
2291			      pScrn->display->modes, clockRanges,
2292			      GetAccelPitchValues(pScrn), 0, 0,
2293			      pScrn->bitsPerPixel, 128, 2048,
2294			      pScrn->display->virtualX,
2295			      pScrn->display->virtualY,
2296			      pTrident->FbMapSize,
2297			      LOOKUP_BEST_REFRESH);
2298    }
2299
2300    if (i == -1) {
2301	if (IsPciCard && UseMMIO) {
2302    	    TRIDENTDisableMMIO(pScrn);
2303 	    TRIDENTUnmapMem(pScrn);
2304	}
2305	TRIDENTFreeRec(pScrn);
2306	return FALSE;
2307    }
2308
2309    /* Prune the modes marked as invalid */
2310    xf86PruneDriverModes(pScrn);
2311
2312    if (i == 0 || pScrn->modes == NULL) {
2313	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
2314	if (IsPciCard && UseMMIO) {
2315    	    TRIDENTDisableMMIO(pScrn);
2316 	    TRIDENTUnmapMem(pScrn);
2317	}
2318	TRIDENTFreeRec(pScrn);
2319	return FALSE;
2320    }
2321
2322    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
2323
2324    /* Set the current mode to the first in the list */
2325    pScrn->currentMode = pScrn->modes;
2326
2327    /* Print the list of modes being used */
2328    xf86PrintModes(pScrn);
2329
2330    /* Set display resolution */
2331    xf86SetDpi(pScrn, 0, 0);
2332
2333    /* Load bpp-specific modules */
2334    switch (pScrn->bitsPerPixel) {
2335    case 8:
2336	pTrident->EngineOperation |= 0x00;
2337	break;
2338    case 16:
2339	pTrident->EngineOperation |= 0x01;
2340	break;
2341    case 24:
2342	pTrident->EngineOperation |= 0x03;
2343	break;
2344    case 32:
2345	pTrident->EngineOperation |= 0x02;
2346	break;
2347    }
2348
2349    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
2350	if (IsPciCard && UseMMIO) {
2351    	    TRIDENTDisableMMIO(pScrn);
2352 	    TRIDENTUnmapMem(pScrn);
2353	}
2354	TRIDENTFreeRec(pScrn);
2355	return FALSE;
2356    }
2357
2358    if (!xf86LoadSubModule(pScrn, "i2c")) {
2359	if (IsPciCard && UseMMIO) {
2360    	    TRIDENTDisableMMIO(pScrn);
2361 	    TRIDENTUnmapMem(pScrn);
2362	}
2363	TRIDENTFreeRec(pScrn);
2364	return FALSE;
2365    }
2366
2367    /* Load shadow if needed */
2368    if (pTrident->ShadowFB) {
2369	if (!xf86LoadSubModule(pScrn, "shadow")) {
2370	    TRIDENTFreeRec(pScrn);
2371	    return FALSE;
2372	}
2373    }
2374
2375    /* Load XAA if needed */
2376    if (!pTrident->NoAccel) {
2377	if (!pTrident->useEXA) {
2378	    if (!xf86LoadSubModule(pScrn, "xaa")) {
2379		if (IsPciCard && UseMMIO) {
2380		    TRIDENTDisableMMIO(pScrn);
2381		    TRIDENTUnmapMem(pScrn);
2382		}
2383		TRIDENTFreeRec(pScrn);
2384		return FALSE;
2385	    }
2386	}
2387
2388	if (pTrident->useEXA) {
2389	    XF86ModReqInfo req;
2390	    int errmaj, errmin;
2391
2392	    memset(&req, 0, sizeof(req));
2393
2394	    req.majorversion = 2;
2395            if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
2396		&errmaj, &errmin))
2397	    {
2398		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
2399		if (IsPciCard && UseMMIO) {
2400		    TRIDENTDisableMMIO(pScrn);
2401		    TRIDENTUnmapMem(pScrn);
2402		}
2403		TRIDENTFreeRec(pScrn);
2404		return FALSE;
2405	    }
2406	}
2407
2408        switch (pScrn->displayWidth * pScrn->bitsPerPixel / 8) {
2409	    case 512:
2410	    case 8192:
2411		pTrident->EngineOperation |= 0x00;
2412		break;
2413	    case 1024:
2414		pTrident->EngineOperation |= 0x04;
2415		break;
2416	    case 2048:
2417		pTrident->EngineOperation |= 0x08;
2418		break;
2419	    case 4096:
2420		pTrident->EngineOperation |= 0x0C;
2421		break;
2422	}
2423    }
2424
2425    /* Load DDC if needed */
2426    /* This gives us DDC1 - we should be able to get DDC2B using i2c */
2427
2428    if (! ddcLoaded)
2429	if (!xf86LoadSubModule(pScrn, "ddc")) {
2430	    if (IsPciCard && UseMMIO) {
2431		TRIDENTDisableMMIO(pScrn);
2432		TRIDENTUnmapMem(pScrn);
2433	    }
2434	    TRIDENTFreeRec(pScrn);
2435	    return FALSE;
2436	}
2437
2438    if (IsPciCard && UseMMIO) {
2439        TRIDENTDisableMMIO(pScrn);
2440	TRIDENTUnmapMem(pScrn);
2441    }
2442
2443#ifndef XSERVER_LIBPCIACCESS
2444    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
2445
2446    if (pTrident->IsCyber && pTrident->MMIOonly)
2447	pScrn->racIoFlags = 0;
2448    else
2449	pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
2450#endif
2451    pTrident->FbMapSize = pScrn->videoRam * 1024;
2452
2453    return TRUE;
2454}
2455
2456/*
2457 * Map the framebuffer and MMIO memory.
2458 */
2459
2460static Bool
2461TRIDENTMapMem(ScrnInfoPtr pScrn)
2462{
2463    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
2464    vgaHWPtr hwp = VGAHWPTR(pScrn);
2465    int mapsize = 0x10000;
2466
2467    if (Is3Dchip) mapsize = 0x20000;
2468
2469    if (IsPciCard && UseMMIO)
2470#ifndef XSERVER_LIBPCIACCESS
2471    	pTrident->IOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
2472		pTrident->PciTag, pTrident->IOAddress, mapsize);
2473#else
2474	{
2475		void **result = (void **)&pTrident->IOBase;
2476		int err = pci_device_map_range(pTrident->PciInfo,
2477						pTrident->IOAddress,
2478						mapsize,
2479						PCI_DEV_MAP_FLAG_WRITABLE,
2480						result);
2481		if (err) {
2482			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2483				"Unable to map IO aperture. %s (%d)\n",
2484				strerror(err), err);
2485		}
2486	}
2487#endif
2488    else {
2489#ifndef XSERVER_LIBPCIACCESS
2490    	pTrident->IOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO,
2491		pTrident->PciTag, pTrident->IOAddress, 0x1000);
2492    	pTrident->IOBase += 0xF00;
2493#else
2494	return FALSE;
2495#endif
2496    }
2497
2498    if (pTrident->IOBase == NULL)
2499	return FALSE;
2500
2501    if (pTrident->Linear) {
2502        if (pTrident->FbMapSize != 0) {
2503#ifndef XSERVER_LIBPCIACCESS
2504	    pTrident->FbBase = xf86MapPciMem(pScrn->scrnIndex,
2505				VIDMEM_FRAMEBUFFER,
2506				 pTrident->PciTag,
2507				 (unsigned long)pTrident->FbAddress,
2508				 pTrident->FbMapSize);
2509#else
2510	    {
2511		void **result = (void **)&pTrident->FbBase;
2512		int err = pci_device_map_range(pTrident->PciInfo,
2513						pTrident->FbAddress,
2514						pTrident->FbMapSize,
2515						PCI_DEV_MAP_FLAG_WRITABLE |
2516						PCI_DEV_MAP_FLAG_WRITE_COMBINE,
2517						result);
2518		if (err) {
2519			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2520				"Unable to map VRAM aperture. %s (%d)\n",
2521				strerror(err), err);
2522		}
2523	    }
2524#endif
2525	    if (pTrident->FbBase == NULL)
2526		return FALSE;
2527    	}
2528    }
2529    else
2530	pTrident->FbBase = hwp->Base;
2531
2532    return TRUE;
2533}
2534
2535/*
2536 * Unmap the framebuffer and MMIO memory.
2537 */
2538
2539static Bool
2540TRIDENTUnmapMem(ScrnInfoPtr pScrn)
2541{
2542    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
2543    int mapsize = 0x10000;
2544
2545    if (Is3Dchip) mapsize = 0x20000;
2546
2547    /*
2548     * Unmap IO registers to virtual address space
2549     */
2550#ifdef XSERVER_LIBPCIACCESS
2551    pci_device_unmap_range(pTrident->PciInfo, (pointer)pTrident->IOBase, mapsize);
2552#else
2553    if (IsPciCard && UseMMIO) {
2554    	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, mapsize);
2555    } else {
2556    	pTrident->IOBase -= 0xF00;
2557    	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, 0x1000);
2558    }
2559#endif
2560    pTrident->IOBase = NULL;
2561
2562    if (pTrident->Linear) {
2563    	if (pTrident->FbMapSize != 0) {
2564#ifdef XSERVER_LIBPCIACCESS
2565	    pci_device_unmap_range(pTrident->PciInfo, (pointer)pTrident->FbBase, pTrident->FbMapSize);
2566#else
2567    	    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->FbBase,
2568							pTrident->FbMapSize);
2569#endif
2570	    pTrident->FbBase = NULL;
2571        }
2572    }
2573
2574    return TRUE;
2575}
2576
2577
2578/*
2579 * This function saves the video state.
2580 */
2581static void
2582TRIDENTSave(ScrnInfoPtr pScrn)
2583{
2584    TRIDENTPtr pTrident;
2585    vgaRegPtr vgaReg;
2586    TRIDENTRegPtr tridentReg;
2587
2588    pTrident = TRIDENTPTR(pScrn);
2589    vgaReg = &VGAHWPTR(pScrn)->SavedReg;
2590    tridentReg = &pTrident->SavedReg;
2591
2592    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP |
2593			     (IsPrimaryCard ? VGA_SR_FONTS : 0));
2594
2595    if (pScrn->progClock)
2596    	TridentSave(pScrn, tridentReg);
2597    else
2598    	TVGASave(pScrn, tridentReg);
2599
2600    if (pTrident->TVChipset != 0)
2601       VIA_SaveTVDepentVGAReg(pScrn);
2602}
2603
2604
2605/*
2606 * Initialise a new mode.  This is currently still using the old
2607 * "initialise struct, restore/write struct to HW" model.  That could
2608 * be changed.
2609 */
2610
2611static Bool
2612TRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
2613{
2614    vgaHWPtr hwp = VGAHWPTR(pScrn);
2615    vgaRegPtr vgaReg;
2616    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
2617    TRIDENTRegPtr tridentReg;
2618
2619    if (!xf86IsPc98()) WAITFORVSYNC;
2620
2621    TridentFindClock(pScrn,mode->Clock);
2622
2623    switch (pTrident->Chipset) {
2624	case TGUI9660:
2625	case TGUI9680:
2626	case PROVIDIA9682:
2627	case PROVIDIA9685:
2628	case IMAGE975:
2629	case IMAGE985:
2630	case BLADE3D:
2631	case CYBERBLADEI7:
2632	case CYBERBLADEI7D:
2633	case CYBERBLADEI1:
2634	case CYBERBLADEI1D:
2635	case CYBERBLADEAI1:
2636	case CYBERBLADEAI1D:
2637	case CYBER9520:
2638	case CYBER9525DVD:
2639	case CYBERBLADEE4:
2640	case CYBER9397:
2641	case CYBER9397DVD:
2642	case BLADEXP:
2643	case CYBERBLADEXPAI1:
2644	case CYBERBLADEXP4:
2645	case XP5:
2646	    /* Get ready for MUX mode */
2647	    if (pTrident->MUX &&
2648		pScrn->bitsPerPixel == 8 &&
2649		!mode->CrtcHAdjusted) {
2650		ErrorF("BARF\n");
2651		mode->CrtcHDisplay >>= 1;
2652		mode->CrtcHSyncStart >>= 1;
2653		mode->CrtcHSyncEnd >>= 1;
2654		mode->CrtcHBlankStart >>= 1;
2655		mode->CrtcHBlankEnd >>= 1;
2656		mode->CrtcHTotal >>= 1;
2657		mode->CrtcHAdjusted = TRUE;
2658	    }
2659	    break;
2660	default:
2661	    if (pScrn->videoRam < 1024 &&
2662		!mode->CrtcHAdjusted) {
2663		mode->CrtcHDisplay <<= 1;
2664		mode->CrtcHSyncStart <<= 1;
2665		mode->CrtcHSyncEnd <<= 1;
2666		mode->CrtcHBlankStart <<= 1;
2667		mode->CrtcHBlankEnd <<= 1;
2668		mode->CrtcHTotal <<= 1;
2669		mode->CrtcHAdjusted = TRUE;
2670	    }
2671	    break;
2672    }
2673
2674    vgaHWUnlock(hwp);
2675    /* Initialise the ModeReg values */
2676    if (!vgaHWInit(pScrn, mode))
2677	return FALSE;
2678
2679    pScrn->vtSema = TRUE;
2680    /*
2681     * We used to do this at a later time.
2682     * Now since READOUT isn't defined any more
2683     * we do it here.
2684     * The original NOTE read:
2685     * TridentInit() has to modify registers
2686     * that have already been set by vgaHWRestore().
2687     * So we call it _after_ vgaHWRestore() has
2688     * programmed these registers.
2689     */
2690    if (pScrn->progClock) {
2691    	if (!TridentInit(pScrn, mode))
2692	    return FALSE;
2693    } else {
2694    	if (!TVGAInit(pScrn, mode))
2695	    return FALSE;
2696    }
2697
2698    /* Program the registers */
2699    vgaHWProtect(pScrn, TRUE);
2700    vgaReg = &hwp->ModeReg;
2701    tridentReg = &pTrident->ModeReg;
2702
2703    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
2704    if (pScrn->progClock)
2705    	TridentRestore(pScrn, tridentReg);
2706    else
2707	TVGARestore(pScrn, tridentReg);
2708
2709    vgaHWProtect(pScrn, FALSE);
2710
2711    if (xf86IsPc98())
2712	PC98TRIDENTEnable(pScrn);
2713
2714    if (pTrident->TVChipset != 0)
2715       VIA_TVInit(pScrn);
2716
2717    return TRUE;
2718}
2719
2720/*
2721 * Restore the initial (text) mode.
2722 */
2723static void
2724TRIDENTRestore(ScrnInfoPtr pScrn)
2725{
2726    vgaHWPtr hwp;
2727    vgaRegPtr vgaReg;
2728    TRIDENTPtr pTrident;
2729    TRIDENTRegPtr tridentReg;
2730
2731    hwp = VGAHWPTR(pScrn);
2732    pTrident = TRIDENTPTR(pScrn);
2733    vgaReg = &hwp->SavedReg;
2734    tridentReg = &pTrident->SavedReg;
2735
2736    vgaHWProtect(pScrn, TRUE);
2737
2738    if (pScrn->progClock)
2739    	TridentRestore(pScrn, tridentReg);
2740    else
2741	TVGARestore(pScrn, tridentReg);
2742
2743    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP |
2744				(IsPrimaryCard ? VGA_SR_FONTS : 0));
2745
2746    if (pTrident->TVChipset != 0)
2747       VIA_RestoreTVDependVGAReg(pScrn);
2748
2749    vgaHWProtect(pScrn, FALSE);
2750}
2751
2752
2753/* Mandatory */
2754
2755/* This gets called at the start of each server generation */
2756
2757static Bool
2758TRIDENTScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
2759{
2760    /* The vgaHW references will disappear one day */
2761    ScrnInfoPtr pScrn;
2762    vgaHWPtr hwp;
2763    TRIDENTPtr pTrident;
2764    int ret;
2765    VisualPtr visual;
2766    unsigned char *FBStart;
2767    int width, height, displayWidth;
2768
2769    /*
2770     * First get the ScrnInfoRec
2771     */
2772    pScrn = xf86Screens[pScreen->myNum];
2773    pTrident = TRIDENTPTR(pScrn);
2774
2775    if (IsPrimaryCard) {
2776	if (!vgaHWMapMem(pScrn))
2777   	    return FALSE;
2778    }
2779
2780    /* Map the TRIDENT memory and MMIO areas */
2781    if (!TRIDENTMapMem(pScrn))
2782	return FALSE;
2783
2784    if (!xf86IsPc98()) {
2785#ifdef VBE_INFO
2786	if (pTrident->vbeModes) {
2787	    pTrident->pVbe = VBEInit(NULL,pTrident->pEnt->index);
2788	    pTrident->Int10 = pTrident->pVbe->pInt10;
2789	} else
2790#endif
2791	{
2792	    if (xf86LoadSubModule(pScrn, "int10")) {
2793		xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Initializing int10\n");
2794		pTrident->Int10 = xf86InitInt10(pTrident->pEnt->index);
2795	    }
2796	}
2797    }
2798
2799    hwp = VGAHWPTR(pScrn);
2800
2801    if (IsPciCard && UseMMIO) {
2802    	TRIDENTEnableMMIO(pScrn);
2803
2804    	/* Initialize the MMIO vgahw functions */
2805    	vgaHWSetMmioFuncs(hwp, pTrident->IOBase, 0);
2806    }
2807
2808    /* Save the current state */
2809    TRIDENTSave(pScrn);
2810
2811    /*
2812     * Some Trident chip on PC-9821 needs setup,
2813     * because VGA chip is not initialized by VGA BIOS.
2814     */
2815    if (IsPciCard && xf86IsPc98()) {
2816	 PC98TRIDENTInit(pScrn);
2817    } else tridentSetModeBIOS(pScrn,pScrn->currentMode);
2818
2819    /* Initialise the first mode */
2820    if (!TRIDENTModeInit(pScrn, pScrn->currentMode))
2821	return FALSE;
2822
2823    /* Darken the screen for aesthetic reasons and set the viewport */
2824    TRIDENTSaveScreen(pScreen, SCREEN_SAVER_ON);
2825    TRIDENTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
2826
2827    /*
2828     * The next step is to setup the screen's visuals, and initialise the
2829     * framebuffer code.  In cases where the framebuffer's default
2830     * choices for things like visual layouts and bits per RGB are OK,
2831     * this may be as simple as calling the framebuffer's ScreenInit()
2832     * function.  If not, the visuals will need to be setup before calling
2833     * a fb ScreenInit() function and fixed up after.
2834     *
2835     * For most PC hardware at depths >= 8, the defaults that fb uses
2836     * are not appropriate.  In this driver, we fixup the visuals after.
2837     */
2838
2839    /*
2840     * Reset visual list.
2841     */
2842    miClearVisualTypes();
2843
2844    /* Setup the visuals we support. */
2845
2846    if (!miSetVisualTypes(pScrn->depth,
2847			  miGetDefaultVisualMask(pScrn->depth),
2848			  pScrn->rgbBits, pScrn->defaultVisual)) {
2849	if (pTrident->pVbe)
2850	    	vbeFree(pTrident->pVbe);
2851	else
2852	    xf86FreeInt10(pTrident->Int10);
2853      return FALSE;
2854    }
2855
2856    miSetPixmapDepths ();
2857
2858    /* FIXME - we don't do shadowfb for < 4 */
2859    displayWidth = pScrn->displayWidth;
2860    if (pTrident->Rotate) {
2861	height = pScrn->virtualX;
2862	width = pScrn->virtualY;
2863    } else {
2864	width = pScrn->virtualX;
2865	height = pScrn->virtualY;
2866    }
2867
2868    if(pTrident->ShadowFB) {
2869 	pTrident->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
2870        pTrident->ShadowPtr = xalloc(pTrident->ShadowPitch * height);
2871	displayWidth = pTrident->ShadowPitch / (pScrn->bitsPerPixel >> 3);
2872        FBStart = pTrident->ShadowPtr;
2873    } else {
2874	pTrident->ShadowFB = FALSE;
2875	pTrident->ShadowPtr = NULL;
2876	FBStart = pTrident->FbBase;
2877    }
2878
2879    /*
2880     * Call the framebuffer layer's ScreenInit function, and fill in other
2881     * pScreen fields.
2882     */
2883
2884    switch (pScrn->bitsPerPixel) {
2885    case 8:
2886    case 16:
2887    case 24:
2888    case 32:
2889	ret = fbScreenInit(pScreen, FBStart, width,
2890			height, pScrn->xDpi, pScrn->yDpi,
2891			displayWidth, pScrn->bitsPerPixel);
2892
2893	break;
2894    default:
2895	xf86DrvMsg(scrnIndex, X_ERROR,
2896		   "Internal error: invalid bpp (%d) in TRIDENTScrnInit\n",
2897		   pScrn->bitsPerPixel);
2898	    ret = FALSE;
2899	break;
2900    }
2901    if (!ret) {
2902	if (pTrident->pVbe)
2903	    vbeFree(pTrident->pVbe);
2904	else
2905	    xf86FreeInt10(pTrident->Int10);
2906	return FALSE;
2907    }
2908    if (pScrn->bitsPerPixel > 8) {
2909        /* Fixup RGB ordering */
2910        visual = pScreen->visuals + pScreen->numVisuals;
2911        while (--visual >= pScreen->visuals) {
2912	    if ((visual->class | DynamicClass) == DirectColor) {
2913		visual->offsetRed = pScrn->offset.red;
2914		visual->offsetGreen = pScrn->offset.green;
2915		visual->offsetBlue = pScrn->offset.blue;
2916		visual->redMask = pScrn->mask.red;
2917		visual->greenMask = pScrn->mask.green;
2918		visual->blueMask = pScrn->mask.blue;
2919	    }
2920	}
2921    }
2922
2923    /* must be after RGB ordering fixed */
2924    fbPictureInit (pScreen, 0, 0);
2925
2926    xf86SetBlackWhitePixels(pScreen);
2927
2928    pTrident->BlockHandler = pScreen->BlockHandler;
2929    pScreen->BlockHandler = TRIDENTBlockHandler;
2930
2931    if (!pTrident->ShadowFB)
2932	TRIDENTDGAInit(pScreen);
2933
2934    if (!pTrident->Linear) {
2935	miBankInfoPtr pBankInfo;
2936
2937	/* Setup the vga banking variables */
2938	pBankInfo = xnfcalloc(sizeof(miBankInfoRec),1);
2939	if (pBankInfo == NULL) {
2940	    if (pTrident->pVbe)
2941		vbeFree(pTrident->pVbe);
2942	    else
2943		xf86FreeInt10(pTrident->Int10);
2944	    return FALSE;
2945	}
2946	pBankInfo->pBankA = pTrident->FbBase;
2947	pBankInfo->pBankB = pTrident->FbBase;
2948	pBankInfo->BankSize = 0x10000;
2949	pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth;
2950
2951	pBankInfo->SetSourceBank =
2952		(miBankProcPtr)TVGA8900SetRead;
2953	pBankInfo->SetDestinationBank =
2954		(miBankProcPtr)TVGA8900SetWrite;
2955	pBankInfo->SetSourceAndDestinationBanks =
2956		(miBankProcPtr)TVGA8900SetReadWrite;
2957	if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY,
2958				 pScrn->displayWidth, pBankInfo)) {
2959	    xfree(pBankInfo);
2960	    pBankInfo = NULL;
2961	    if (pTrident->pVbe)
2962	    	vbeFree(pTrident->pVbe);
2963	    else
2964		xf86FreeInt10(pTrident->Int10);
2965	    return FALSE;
2966	}
2967    }
2968
2969    {
2970    	BoxRec AvailFBArea;
2971
2972	AvailFBArea.x1 = 0;
2973    	AvailFBArea.y1 = 0;
2974    	AvailFBArea.x2 = pScrn->displayWidth;
2975    	AvailFBArea.y2 = pTrident->FbMapSize / (pScrn->displayWidth *
2976					    pScrn->bitsPerPixel / 8);
2977
2978    	if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047;
2979
2980    	if (xf86InitFBManager(pScreen, &AvailFBArea)) {
2981	    int cpp = pScrn->bitsPerPixel / 8;
2982	    int area = AvailFBArea.y2 * pScrn->displayWidth;
2983	    int areaoffset = area * cpp;
2984
2985    	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2986	       "Using %i scanlines of offscreen memory for area's \n",
2987 	       AvailFBArea.y2 - pScrn->virtualY);
2988
2989	    if (xf86InitFBManagerLinear(pScreen, area, ((pTrident->FbMapSize/cpp) - area))) {
2990		xf86DrvMsg(scrnIndex, X_INFO,
2991			"Using %ld bytes of offscreen memory for linear (offset=0x%x)\n", (pTrident->FbMapSize - areaoffset), areaoffset);
2992	    }
2993    	}
2994    }
2995
2996    if (Is3Dchip) {
2997	if ((pTrident->Chipset == CYBERBLADEI7) ||
2998	    (pTrident->Chipset == CYBERBLADEI7D) ||
2999	    (pTrident->Chipset == CYBERBLADEI1) ||
3000	    (pTrident->Chipset == CYBERBLADEI1D) ||
3001	    (pTrident->Chipset == CYBERBLADEAI1) ||
3002	    (pTrident->Chipset == CYBERBLADEAI1D) ||
3003	    (pTrident->Chipset == CYBERBLADEE4) ||
3004	    (pTrident->Chipset == BLADE3D)) {
3005	    if (pTrident->useEXA)
3006		BladeExaInit(pScreen);
3007	    else
3008		BladeXaaInit(pScreen);
3009	} else
3010	if ((pTrident->Chipset == CYBERBLADEXP4) ||
3011	    (pTrident->Chipset == XP5)) {
3012	    if (pTrident->useEXA)
3013	    	XP4ExaInit(pScreen);
3014	    else
3015		XP4XaaInit(pScreen);
3016	} else
3017	if ((pTrident->Chipset == BLADEXP) ||
3018	    (pTrident->Chipset == CYBERBLADEXPAI1)) {
3019		XPAccelInit(pScreen);
3020	} else {
3021	    	ImageAccelInit(pScreen);
3022	}
3023    } else {
3024    	TridentAccelInit(pScreen);
3025    }
3026
3027    miInitializeBackingStore(pScreen);
3028    xf86SetBackingStore(pScreen);
3029
3030    /* Initialise cursor functions */
3031    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
3032
3033    if (pTrident->HWCursor) {
3034        xf86SetSilkenMouse(pScreen);
3035	TridentHWCursorInit(pScreen);
3036    }
3037
3038    /* Initialise default colourmap */
3039    if (!miCreateDefColormap(pScreen)) {
3040	if (pTrident->pVbe)
3041	    vbeFree(pTrident->pVbe);
3042	else
3043	    xf86FreeInt10(pTrident->Int10);
3044	return FALSE;
3045    }
3046    if(!xf86HandleColormaps(pScreen, 256, 6, TridentLoadPalette,
3047			    TridentSetOverscan, CMAP_RELOAD_ON_MODE_SWITCH|CMAP_PALETTED_TRUECOLOR)) {
3048	if (pTrident->pVbe)
3049	    vbeFree(pTrident->pVbe);
3050	else
3051	    xf86FreeInt10(pTrident->Int10);
3052	return FALSE;
3053    }
3054    if(pTrident->ShadowFB) {
3055        if(pTrident->Rotate) {
3056	    if (!pTrident->PointerMoved) {
3057	        pTrident->PointerMoved = pScrn->PointerMoved;
3058		pScrn->PointerMoved = TRIDENTPointerMoved;
3059	    }
3060	    switch (pScrn->bitsPerPixel) {
3061	    case 8:    pTrident->RefreshArea = TRIDENTRefreshArea8; break;
3062	    case 16:   pTrident->RefreshArea = TRIDENTRefreshArea16; break;
3063	    case 24:   pTrident->RefreshArea = TRIDENTRefreshArea24; break;
3064	    case 32:   pTrident->RefreshArea = TRIDENTRefreshArea32; break;
3065	    }
3066	} else {
3067	  pTrident->RefreshArea = TRIDENTRefreshArea;
3068	}
3069	shadowInit (pScreen, TRIDENTShadowUpdate, 0);
3070    }
3071
3072    xf86DPMSInit(pScreen, (DPMSSetProcPtr)TRIDENTDisplayPowerManagementSet, 0);
3073
3074    pScrn->memPhysBase = pTrident->FbAddress;
3075    pScrn->fbOffset = 0;
3076
3077    if (pTrident->Chipset >= TGUI9660)
3078	TRIDENTInitVideo(pScreen);
3079
3080    pTrident->CloseScreen = pScreen->CloseScreen;
3081    pScreen->CloseScreen = TRIDENTCloseScreen;
3082    pScreen->SaveScreen = TRIDENTSaveScreen;
3083
3084    /* Report any unused options (only for the first generation) */
3085    if (serverGeneration == 1) {
3086	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
3087    }
3088
3089#if 0
3090    TRIDENTI2CInit(pScreen);
3091
3092    xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,pTrident->DDC));
3093#endif
3094
3095    return TRUE;
3096}
3097
3098/* Usually mandatory */
3099Bool
3100TRIDENTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
3101{
3102    return TRIDENTModeInit(xf86Screens[scrnIndex], mode);
3103}
3104
3105
3106/*
3107 * This function is used to initialize the Start Address - the first
3108 * displayed location in the video memory.
3109 */
3110/* Usually mandatory */
3111void
3112TRIDENTAdjustFrame(int scrnIndex, int x, int y, int flags)
3113{
3114    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3115    TRIDENTPtr pTrident;
3116    int base = y * pScrn->displayWidth + x;
3117    int vgaIOBase;
3118    CARD8 temp;
3119
3120    pTrident = TRIDENTPTR(pScrn);
3121    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
3122
3123    switch (pScrn->bitsPerPixel) {
3124	case 8:
3125	    if (pScrn->progClock)
3126	    	base = (base & 0xFFFFFFF8) >> 2;
3127	    else
3128	    	base = (base & 0xFFFFFFF8) >> 3;
3129	    break;
3130	case 16:
3131	    base >>= 1;
3132	    break;
3133	case 24:
3134	    base = (((base + 1) & ~0x03) * 3) >> 2;
3135	    break;
3136	case 32:
3137	    break;
3138    }
3139
3140    /* CRT bits 0-15 */
3141    OUTW(vgaIOBase + 4, (base & 0x00FF00) | 0x0C);
3142    OUTW(vgaIOBase + 4, ((base & 0x00FF) << 8) | 0x0D);
3143    /* CRT bit 16 */
3144    OUTB(vgaIOBase + 4, CRTCModuleTest); temp = INB(vgaIOBase + 5) & 0xDF;
3145    OUTB(vgaIOBase + 5, temp | ((base & 0x10000) >> 11));
3146    /* CRT bit 17-19 */
3147    OUTB(vgaIOBase + 4, CRTHiOrd); temp = INB(vgaIOBase + 5) & 0xF8;
3148    OUTB(vgaIOBase + 5, temp | ((base & 0xE0000) >> 17));
3149}
3150
3151
3152/*
3153 * This is called when VT switching back to the X server.  Its job is
3154 * to reinitialise the video mode.
3155 */
3156
3157/* Mandatory */
3158static Bool
3159TRIDENTEnterVT(int scrnIndex, int flags)
3160{
3161    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3162    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3163
3164    if (IsPciCard && UseMMIO) TRIDENTEnableMMIO(pScrn);
3165
3166    /* Should we re-save the text mode on each VT enter? */
3167    if (!TRIDENTModeInit(pScrn, pScrn->currentMode))
3168	return FALSE;
3169
3170    if (pTrident->InitializeAccelerator)
3171        pTrident->InitializeAccelerator(pScrn);
3172
3173    return TRUE;
3174}
3175
3176
3177/*
3178 * This is called when VT switching away from the X server.  Its job is
3179 * to restore the previous (text) mode.
3180 *
3181 * We may wish to remap video/MMIO memory too.
3182 */
3183
3184/* Mandatory */
3185static void
3186TRIDENTLeaveVT(int scrnIndex, int flags)
3187{
3188    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3189    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3190    vgaHWPtr hwp = VGAHWPTR(pScrn);
3191
3192    if (!pTrident->NoAccel && !pTrident->useEXA)
3193	pTrident->AccelInfoRec->Sync(pScrn);
3194    else if (!pTrident->NoAccel && pTrident->useEXA)
3195	pTrident->EXADriverPtr->WaitMarker(pScrn->pScreen, 0);
3196
3197    TRIDENTRestore(pScrn);
3198    vgaHWLock(hwp);
3199
3200    if (xf86IsPc98())
3201	PC98TRIDENTDisable(pScrn);
3202
3203    if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn);
3204}
3205
3206
3207/*
3208 * This is called at the end of each server generation.  It restores the
3209 * original (text) mode.  It should really also unmap the video memory too.
3210 */
3211
3212/* Mandatory */
3213static Bool
3214TRIDENTCloseScreen(int scrnIndex, ScreenPtr pScreen)
3215{
3216    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3217    vgaHWPtr hwp = VGAHWPTR(pScrn);
3218    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3219
3220    if (pScrn->vtSema) {
3221    if (!pTrident->NoAccel && !pTrident->useEXA)
3222	pTrident->AccelInfoRec->Sync(pScrn);
3223    else if (!pTrident->NoAccel && pTrident->useEXA)
3224	pTrident->EXADriverPtr->WaitMarker(pScreen, 0);
3225
3226    if (xf86IsPc98())
3227	PC98TRIDENTDisable(pScrn);
3228
3229    	TRIDENTRestore(pScrn);
3230    	vgaHWLock(hwp);
3231	if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn);
3232    	TRIDENTUnmapMem(pScrn);
3233    }
3234    if (pTrident->AccelInfoRec)
3235	XAADestroyInfoRec(pTrident->AccelInfoRec);
3236    if (pTrident->EXADriverPtr) {
3237	exaDriverFini(pScreen);
3238	xfree(pTrident->EXADriverPtr);
3239	pTrident->EXADriverPtr = NULL;
3240    }
3241    if (pTrident->CursorInfoRec)
3242	xf86DestroyCursorInfoRec(pTrident->CursorInfoRec);
3243    if (pTrident->ShadowPtr)
3244	xfree(pTrident->ShadowPtr);
3245    if (pTrident->DGAModes)
3246	xfree(pTrident->DGAModes);
3247    pScrn->vtSema = FALSE;
3248
3249    if(pTrident->BlockHandler)
3250	pScreen->BlockHandler = pTrident->BlockHandler;
3251
3252    if (pTrident->pVbe)
3253	vbeFree(pTrident->pVbe);
3254    else
3255	xf86FreeInt10(pTrident->Int10);
3256    pScreen->CloseScreen = pTrident->CloseScreen;
3257    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
3258}
3259
3260
3261/* Free up any per-generation data structures */
3262
3263/* Optional */
3264static void
3265TRIDENTFreeScreen(int scrnIndex, int flags)
3266{
3267    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
3268	vgaHWFreeHWRec(xf86Screens[scrnIndex]);
3269    TRIDENTFreeRec(xf86Screens[scrnIndex]);
3270}
3271
3272
3273/* Checks if a mode is suitable for the selected chipset. */
3274
3275/* Optional */
3276static ModeStatus
3277TRIDENTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
3278{
3279    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
3280    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3281
3282    if (pTrident->lcdActive && (pTrident->lcdMode != 0xff)){
3283	if (((mode->HDisplay > LCD[pTrident->lcdMode].display_x)
3284	|| (mode->VDisplay > LCD[pTrident->lcdMode].display_y))) {
3285	    xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) "
3286		       "larger than the LCD panel (%dx%d)\n",
3287		       mode->HDisplay,
3288		       mode->VDisplay,
3289		       LCD[pTrident->lcdMode].display_x,
3290		       LCD[pTrident->lcdMode].display_y);
3291	    return(MODE_BAD);
3292	}
3293	if (((float)mode->HDisplay/(float)mode->VDisplay) > 2.0) {
3294	    xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) "
3295		       "unusual aspect ratio\n",
3296		       mode->HDisplay,
3297		       mode->VDisplay);
3298	    return(MODE_BAD);
3299	}
3300    }
3301    return (MODE_OK);
3302}
3303
3304/* Do screen blanking */
3305
3306/* Mandatory */
3307static Bool
3308TRIDENTSaveScreen(ScreenPtr pScreen, int mode)
3309{
3310    return vgaHWSaveScreen(pScreen, mode);
3311}
3312
3313static void
3314TRIDENTEnableMMIO(ScrnInfoPtr pScrn)
3315{
3316    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3317    IOADDRESS vgaIOBase = pTrident->PIOBase + VGAHWPTR(pScrn)->IOBase;
3318    CARD8 temp = 0, protect = 0;
3319
3320    /*
3321     * Skip MMIO Enable in PC-9821 PCI Trident Card!!
3322     * Because of lack of non PCI VGA port
3323     */
3324    if (IsPciCard && xf86IsPc98())
3325      return;
3326
3327    /* Goto New Mode */
3328    outb(pTrident->PIOBase + 0x3C4, 0x0B);
3329    inb(pTrident->PIOBase + 0x3C5);
3330
3331    /* Unprotect registers */
3332    if (pTrident->Chipset > PROVIDIA9685) {
3333    	outb(pTrident->PIOBase + 0x3C4, Protection);
3334    	protect = inb(pTrident->PIOBase + 0x3C5);
3335    	outb(pTrident->PIOBase + 0x3C5, 0x92);
3336    }
3337    outb(pTrident->PIOBase + 0x3C4, NewMode1);
3338    temp = inb(pTrident->PIOBase + 0x3C5);
3339    outb(pTrident->PIOBase + 0x3C5, 0x80);
3340
3341    /* Enable MMIO */
3342    outb(vgaIOBase + 4, PCIReg);
3343    pTrident->REGPCIReg = inb(vgaIOBase + 5);
3344    outb(vgaIOBase + 5, pTrident->REGPCIReg | 0x01); /* Enable it */
3345
3346    /* Protect registers */
3347    if (pTrident->Chipset > PROVIDIA9685) {
3348    	OUTB(0x3C4, Protection);
3349    	OUTB(0x3C5, protect);
3350    }
3351    OUTB(0x3C4, NewMode1);
3352    OUTB(0x3C5, temp);
3353}
3354
3355static void
3356TRIDENTDisableMMIO(ScrnInfoPtr pScrn)
3357{
3358    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
3359    CARD8 temp = 0, protect = 0;
3360    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3361
3362    /*
3363     * Skip MMIO Disable in PC-9821 PCI Trident Card!!
3364     * Because of lack of non PCI VGA port
3365     */
3366    if (IsPciCard && xf86IsPc98())
3367      return;
3368
3369    /* Goto New Mode */
3370    OUTB(0x3C4, 0x0B); temp = INB(0x3C5);
3371
3372    /* Unprotect registers */
3373    OUTB(0x3C4, NewMode1); temp = INB(0x3C5);
3374    OUTB(0x3C5, 0x80);
3375    if (pTrident->Chipset > PROVIDIA9685) {
3376    	OUTB(0x3C4, Protection);
3377    	protect = INB(0x3C5);
3378    	OUTB(0x3C5, 0x92);
3379    }
3380
3381    /* Disable MMIO access */
3382    OUTB(vgaIOBase + 4, PCIReg);
3383    pTrident->REGPCIReg = INB(vgaIOBase + 5);
3384    OUTB(vgaIOBase + 5, pTrident->REGPCIReg & 0xFE);
3385
3386    /* Protect registers */
3387    if (pTrident->Chipset > PROVIDIA9685) {
3388    	outb(pTrident->PIOBase + 0x3C4, Protection);
3389    	outb(pTrident->PIOBase + 0x3C5, protect);
3390    }
3391    outb(pTrident->PIOBase + 0x3C4, NewMode1);
3392    outb(pTrident->PIOBase + 0x3C5, temp);
3393}
3394
3395/* Initialize VGA Block for Trident Chip on PC-98x1 */
3396static void
3397PC98TRIDENTInit(ScrnInfoPtr pScrn)
3398{
3399    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3400    switch (pTrident->Chipset) {
3401    case TGUI9660:
3402    case TGUI9680:
3403    case PROVIDIA9682:
3404	PC98TRIDENT96xxInit(pScrn);
3405	break;
3406    case CYBER9320:
3407    case CYBER9385:
3408	PC98TRIDENT9385Init(pScrn);
3409	break;
3410    default: /* Run 96xx code as default */
3411	PC98TRIDENT96xxInit(pScrn);
3412	break;
3413    }
3414}
3415
3416static void
3417PC98TRIDENTEnable(ScrnInfoPtr pScrn)
3418{
3419    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3420    switch (pTrident->Chipset) {
3421    case TGUI9660:
3422    case TGUI9680:
3423    case PROVIDIA9682:
3424	PC98TRIDENT96xxEnable(pScrn);
3425	break;
3426    case CYBER9320:
3427    case CYBER9385:
3428	PC98TRIDENT9385Enable(pScrn);
3429	break;
3430    default: /* Run 96xx code as default */
3431	PC98TRIDENT96xxEnable(pScrn);
3432	break;
3433    }
3434}
3435
3436static void
3437PC98TRIDENTDisable(ScrnInfoPtr pScrn)
3438{
3439    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3440    switch (pTrident->Chipset) {
3441    case TGUI9660:
3442    case TGUI9680:
3443    case PROVIDIA9682:
3444	PC98TRIDENT96xxDisable(pScrn);
3445	break;
3446    case CYBER9320:
3447    case CYBER9385:
3448	PC98TRIDENT9385Disable(pScrn);
3449	break;
3450    default: /* Run 96xx code as default */
3451	PC98TRIDENT96xxDisable(pScrn);
3452	break;
3453    }
3454}
3455
3456/* Initialize VGA Block for Cyber9385 on PC-98x1 */
3457static void
3458PC98TRIDENT9385Init(ScrnInfoPtr pScrn)
3459{
3460/* Nothing to initialize */
3461}
3462
3463static void
3464PC98TRIDENT9385Enable(ScrnInfoPtr pScrn)
3465{
3466    outb(0xFAC, 0x02);
3467}
3468
3469static void
3470PC98TRIDENT9385Disable(ScrnInfoPtr pScrn)
3471{
3472    outb(0xFAC, 0x00);
3473}
3474
3475/* Initialize VGA Block for Trident96xx on PC-98x1 */
3476static void
3477PC98TRIDENT96xxInit(ScrnInfoPtr pScrn)
3478{
3479    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3480    vgaHWPtr hwp = VGAHWPTR(pScrn);
3481    CARD8 temp = 0;
3482
3483    vgaHWProtect(pScrn, TRUE);
3484
3485    /* Video SusSystem Enable */
3486    temp = INB(0x3CC);
3487    OUTB(0x3C2, temp | 0xC3);
3488    /* Switch Old */
3489    OUTB(0x3C4, 0x0B); temp = INB(0x3C5);
3490    OUTW(0x3C4, 0x0B | (temp << 8));
3491    /* Select Configuration Port 1 */
3492    OUTB(0x3C4, 0x0E); temp = INB(0x3C5);
3493    OUTW(0x3C4, 0x0E | ((temp | 0x20) << 8));
3494
3495    OUTB(0x3C4, 0x0c);
3496    if((INB(0x3C5) & 0x10) == 0x10)
3497    {
3498	OUTB(0x3C4, 0x0E | (temp << 8));
3499	OUTB(0x94,  0x00);
3500	OUTB(0x102, 0x01);
3501	OUTB(0x94,  0x20);
3502	temp = INB(0x3C3);
3503	OUTB(0x3C3, temp | 0x01);
3504    } else {
3505	OUTB(0x3C4, 0x0E | (temp << 8));
3506	OUTB(0x46E8, 0x10);
3507	OUTB(0x102,  0x01);
3508	OUTB(0x46E8, 0x08);
3509    }
3510
3511    INB(0x3DA);
3512    OUTB(0x3C0,0x10);
3513    OUTB(0x3C0,0x41);
3514
3515    /* Register Unlock */
3516    vgaHWUnlock(hwp);
3517    OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Switch New */
3518    OUTB(0x3C4, 0x0E); temp = INB(0x3C5);
3519    OUTW(0x3C4, 0x0E | ((temp | 0x80) << 8));
3520
3521    /* For Speed Up [Facoor 2 at Xengine] */
3522    OUTW(0x3D4, 0x3820); /* Command FIFO Register */
3523    OUTW(0x3D4, 0x2020); /* Command FIFO Register */
3524    /* Latency Control Registers 0x30 - 0x32 */
3525    /* Parameter Range 0x00 - 0x0F */
3526    /* Tune these parameter to avoid GE Timeout */
3527    OUTW(0x3D4, 0x0E30); /* Display Queue Latency Control */
3528    /* 8bpp GE No Timeout Parameter 0x0D - 0x0F for PC-9821Xa7 TGUi9680 */
3529    OUTW(0x3D4, 0x0031); /* Frame Buffer Latency Control */
3530    OUTW(0x3D4, 0x0032); /* Display & Frame Buffer Latency Control */
3531    OUTW(0x3D4, 0x213B); /* Clock and Tuning */
3532
3533    /* MCLK Init */
3534    OUTB(0x43C6, 0xAF); OUTB(0x43C7, 0x00); /* 80.0MHz */
3535#if 0
3536    /* Sample MCLKs */
3537    OUTB(0x43C6, 0xAF); OUTB(0x43C7, 0x00); /* 80.0MHz */
3538    OUTB(0x43C6, 0xA7); OUTB(0x43C7, 0x00); /* 77.0MHz */
3539    OUTB(0x43C6, 0x8E); OUTB(0x43C7, 0x00); /* 75.0MHz */
3540    OUTB(0x43C6, 0x86); OUTB(0x43C7, 0x00); /* 72.0MHz */
3541    OUTB(0x43C6, 0x8F); OUTB(0x43C7, 0x00); /* 67.2MHz */
3542    OUTB(0x43C6, 0xD5); OUTB(0x43C7, 0x02); /* 61.6MHz */
3543#endif
3544
3545    /* Register Lock */
3546    OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Switch New */
3547    OUTB(0x3C4, 0x0E); temp = INB(0x3C5);
3548    OUTW(0x3C4, 0x0E | ((temp & 0x7F) << 8));
3549    vgaHWLock(hwp);
3550
3551    vgaHWProtect(pScrn, FALSE);
3552}
3553
3554static void
3555PC98TRIDENT96xxEnable(ScrnInfoPtr pScrn)
3556{
3557    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3558    CARD8 temp = 0;
3559
3560    outb(0x68, 0x0E);
3561    outb(0x6A, 0x07);
3562    outb(0x6A, 0x8F);
3563    outb(0x6A, 0x06);
3564
3565    vgaHWProtect(pScrn, TRUE);
3566
3567    OUTB(0x3D4, 0x23); temp = INB(0x3D5);
3568    OUTW(0x3D4, 0x23 | ((temp & 0xDF) << 8));
3569
3570    OUTB(0x3D4, 0x29); temp = INB(0x3D5);
3571    OUTW(0x3D4, 0x29 | ((temp | 0x04) << 8));
3572
3573    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3574    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x06));
3575
3576    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3577    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x08));
3578
3579    OUTB(0x3CE, 0x23); temp = INB(0x3CF);
3580    OUTW(0x3CE, 0x23 | ((temp & 0xFC) << 8));
3581
3582    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3583    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x01));
3584
3585    OUTB(0x3C4, 0x01); temp = INB(0x3C5);
3586    OUTW(0x3C4, 0x01 | ((temp & 0xEF) << 8));
3587
3588    vgaHWProtect(pScrn, FALSE);
3589
3590    outb(0xFAC, 0x02);
3591}
3592
3593static void
3594PC98TRIDENT96xxDisable(ScrnInfoPtr pScrn)
3595{
3596    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3597    CARD8 temp = 0;
3598
3599    outb(0xFAC, 0x00);
3600
3601    vgaHWProtect(pScrn, TRUE);
3602
3603    OUTB(0x3C4, 0x01); temp = INB(0x3C5);
3604    OUTW(0x3C4, 0x01 | ((temp | 0x10) << 8));
3605
3606    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3607    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFE));
3608
3609    OUTB(0x3CE, 0x23); temp = INB(0x3CF);
3610    OUTW(0x3CE, 0x23 | (((temp & 0xFC) | 0x01) << 8));
3611
3612    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3613    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFD));
3614
3615    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3616    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xCF));
3617
3618    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3619    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xF7));
3620
3621    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
3622    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFB));
3623
3624    OUTB(0x3D4, 0x29); temp = INB(0x3D5);
3625    OUTW(0x3D4, 0x29 | ((temp & 0xFB) << 8));
3626
3627    OUTB(0x3D4, 0x23); temp = INB(0x3D5);
3628    OUTW(0x3D4, 0x23 | ((temp | 0x20) << 8));
3629
3630    vgaHWProtect(pScrn, FALSE);
3631
3632    outb(0x6A, 0x07);
3633    outb(0x6A, 0x8E);
3634    outb(0x6A, 0x06);
3635    outb(0x68, 0x0F);
3636}
3637
3638
3639/*
3640 * This is a terrible hack! If we are on a notebook in a stretched
3641 * mode and don't want full screen we use the BIOS to set an unstreched
3642 * mode.
3643 */
3644void
3645tridentSetModeBIOS(ScrnInfoPtr pScrn, DisplayModePtr mode)
3646{
3647    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
3648
3649
3650#ifdef VBE_INFO
3651    if (pTrident->vbeModes) {
3652	vbeSaveRestoreRec vbesr;
3653	vbesr.stateMode = VBECalcVbeModeIndex(pTrident->vbeModes,
3654					     mode, pScrn->bitsPerPixel);
3655	vbesr.pstate = NULL;
3656	if (vbesr.stateMode) {
3657	    if (IsPciCard && UseMMIO)
3658		TRIDENTDisableMMIO(pScrn);
3659	    VBEVesaSaveRestore(pTrident->pVbe,&vbesr,MODE_RESTORE);
3660	    if (IsPciCard && UseMMIO)
3661		TRIDENTEnableMMIO(pScrn);
3662	    return;
3663	} else
3664	    xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"No BIOS Mode matches "
3665		       "%ix%I@%ibpp\n",mode->HDisplay,mode->VDisplay,
3666		       pScrn->bitsPerPixel);
3667    }
3668#endif
3669    /* This function is only for LCD screens, and also when we have
3670     * int10 available */
3671
3672    if (pTrident->IsCyber && pTrident->lcdMode && pTrident->Int10) {
3673        int i = pTrident->lcdMode;
3674	if ((pScrn->currentMode->HDisplay != LCD[i].display_x) /* !fullsize? */
3675	    || (pScrn->currentMode->VDisplay != LCD[i].display_y)) {
3676	    if (pTrident->lcdActive)  { /* LCD Active ?*/
3677	        int h_str, v_str;
3678
3679		OUTB(0x3CE,HorStretch);  h_str = INB(0x3CF) & 0x01;
3680		OUTB(0x3CE,VertStretch); v_str = INB(0x3CF) & 0x01;
3681		if (h_str || v_str) {
3682		    OUTB(0x3C4, 0x11); OUTB(0x3C5, 0x92);
3683		    OUTW(0x3CE, BiosReg );
3684		    pTrident->Int10->ax = 0x3;
3685		    pTrident->Int10->num = 0x10;
3686		    if (IsPciCard && UseMMIO)
3687			TRIDENTDisableMMIO(pScrn);
3688		    xf86ExecX86int10(pTrident->Int10);
3689		    if (IsPciCard && UseMMIO)
3690			TRIDENTEnableMMIO(pScrn);
3691		}
3692	    }
3693	}
3694    }
3695}
3696
3697/* Currently we only test for 1400 */
3698static int
3699TRIDENTLcdDisplaySize (xf86MonPtr pMon)
3700{
3701    if (pMon) {
3702	int i,j;
3703
3704	for (i = 0; i < STD_TIMINGS; i++) {
3705	    if (pMon->timings2[i].hsize == 1400) {
3706		return 1400;
3707	    }
3708	}
3709	/*
3710	 * If not explicitely set try to find out if the display supports
3711	 * the 1400 mode. For sanity check if DDC comes from a digital
3712	 * display.
3713	 */
3714	if (DIGITAL(pMon->features.input_type)) {
3715	    for (i = 0; i < DET_TIMINGS; i++) {
3716		if (pMon->det_mon[i].type == DS_STD_TIMINGS) {
3717		    for (j = 0; j < 5; j++) {
3718			if (pMon->det_mon[i].section.std_t[j].hsize == 1400) {
3719			    return 1400;
3720			}
3721		    }
3722		} else if (pMon->det_mon[i].type == DT) {
3723		    if (pMon->det_mon[i].section.d_timings.h_active == 1400) {
3724			return 1400;
3725		    }
3726		}
3727	    }
3728	}
3729    }
3730    return 0;
3731}
3732
3733