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