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