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