trident_driver.c revision 95b296d0
195b296d0Smrg/*
295b296d0Smrg * Copyright 1992-2003 by Alan Hourihane, North Wales, UK.
395b296d0Smrg *
495b296d0Smrg * Permission to use, copy, modify, distribute, and sell this software and its
595b296d0Smrg * documentation for any purpose is hereby granted without fee, provided that
695b296d0Smrg * the above copyright notice appear in all copies and that both that
795b296d0Smrg * copyright notice and this permission notice appear in supporting
895b296d0Smrg * documentation, and that the name of Alan Hourihane not be used in
995b296d0Smrg * advertising or publicity pertaining to distribution of the software without
1095b296d0Smrg * specific, written prior permission.  Alan Hourihane makes no representations
1195b296d0Smrg * about the suitability of this software for any purpose.  It is provided
1295b296d0Smrg * "as is" without express or implied warranty.
1395b296d0Smrg *
1495b296d0Smrg * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1595b296d0Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1695b296d0Smrg * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1795b296d0Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1895b296d0Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1995b296d0Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2095b296d0Smrg * PERFORMANCE OF THIS SOFTWARE.
2195b296d0Smrg *
2295b296d0Smrg * Author:  Alan Hourihane, alanh@fairlite.demon.co.uk
2395b296d0Smrg *	    Re-written for XFree86 v4.0
2495b296d0Smrg *
2595b296d0Smrg * Previous driver (pre-XFree86 v4.0) by
2695b296d0Smrg * 	    Alan Hourihane, alanh@fairlite.demon.co.uk
2795b296d0Smrg *	    David Wexelblat (major contributor)
2895b296d0Smrg *	    Massimiliano Ghilardi, max@Linuz.sns.it, some fixes to the
2995b296d0Smrg *				   clockchip programming code.
3095b296d0Smrg */
3195b296d0Smrg/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/trident/trident_driver.c,v 1.190 2004/01/21 22:31:54 alanh Exp $ */
3295b296d0Smrg
3395b296d0Smrg#ifdef HAVE_CONFIG_H
3495b296d0Smrg#include "config.h"
3595b296d0Smrg#endif
3695b296d0Smrg
3795b296d0Smrg#include "fb.h"
3895b296d0Smrg
3995b296d0Smrg#include "mibank.h"
4095b296d0Smrg#include "micmap.h"
4195b296d0Smrg#include "xf86.h"
4295b296d0Smrg#include "xf86_OSproc.h"
4395b296d0Smrg#include "xf86Resources.h"
4495b296d0Smrg#include "xf86Version.h"
4595b296d0Smrg#include "xf86PciInfo.h"
4695b296d0Smrg#include "xf86Pci.h"
4795b296d0Smrg#include "xf86cmap.h"
4895b296d0Smrg#include "vgaHW.h"
4995b296d0Smrg#include "xf86RAC.h"
5095b296d0Smrg#include "vbe.h"
5195b296d0Smrg#include "dixstruct.h"
5295b296d0Smrg#include "compiler.h"
5395b296d0Smrg
5495b296d0Smrg#include "mipointer.h"
5595b296d0Smrg
5695b296d0Smrg#include "mibstore.h"
5795b296d0Smrg#include "shadow.h"
5895b296d0Smrg#include "trident.h"
5995b296d0Smrg#include "trident_regs.h"
6095b296d0Smrg
6195b296d0Smrg#ifdef XFreeXDGA
6295b296d0Smrg#define _XF86DGA_SERVER_
6395b296d0Smrg#include <X11/extensions/xf86dgastr.h>
6495b296d0Smrg#endif
6595b296d0Smrg
6695b296d0Smrg#include "globals.h"
6795b296d0Smrg#define DPMS_SERVER
6895b296d0Smrg#include <X11/extensions/dpms.h>
6995b296d0Smrg
7095b296d0Smrg#include "xf86xv.h"
7195b296d0Smrg
7295b296d0Smrgstatic const OptionInfoRec * TRIDENTAvailableOptions(int chipid, int busid);
7395b296d0Smrgstatic void	TRIDENTIdentify(int flags);
7495b296d0Smrgstatic Bool	TRIDENTProbe(DriverPtr drv, int flags);
7595b296d0Smrgstatic Bool	TRIDENTPreInit(ScrnInfoPtr pScrn, int flags);
7695b296d0Smrgstatic Bool	TRIDENTScreenInit(int Index, ScreenPtr pScreen, int argc,
7795b296d0Smrg			      char **argv);
7895b296d0Smrgstatic Bool	TRIDENTEnterVT(int scrnIndex, int flags);
7995b296d0Smrgstatic void	TRIDENTLeaveVT(int scrnIndex, int flags);
8095b296d0Smrgstatic Bool	TRIDENTCloseScreen(int scrnIndex, ScreenPtr pScreen);
8195b296d0Smrgstatic Bool	TRIDENTSaveScreen(ScreenPtr pScreen, int mode);
8295b296d0Smrg
8395b296d0Smrg/* Optional functions */
8495b296d0Smrgstatic void	TRIDENTFreeScreen(int scrnIndex, int flags);
8595b296d0Smrgstatic ModeStatus TRIDENTValidMode(int scrnIndex, DisplayModePtr mode,
8695b296d0Smrg				   Bool verbose, int flags);
8795b296d0Smrg
8895b296d0Smrg/* Internally used functions */
8995b296d0Smrgstatic Bool	TRIDENTMapMem(ScrnInfoPtr pScrn);
9095b296d0Smrgstatic Bool	TRIDENTUnmapMem(ScrnInfoPtr pScrn);
9195b296d0Smrgstatic void	TRIDENTSave(ScrnInfoPtr pScrn);
9295b296d0Smrgstatic void	TRIDENTRestore(ScrnInfoPtr pScrn);
9395b296d0Smrgstatic Bool	TRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode);
9495b296d0Smrgstatic void 	TRIDENTBlockHandler(int, pointer, pointer, pointer);
9595b296d0Smrg
9695b296d0Smrgstatic void	TRIDENTEnableMMIO(ScrnInfoPtr pScrn);
9795b296d0Smrgstatic void	TRIDENTDisableMMIO(ScrnInfoPtr pScrn);
9895b296d0Smrgstatic void	PC98TRIDENTInit(ScrnInfoPtr pScrn);
9995b296d0Smrgstatic void	PC98TRIDENTEnable(ScrnInfoPtr pScrn);
10095b296d0Smrgstatic void	PC98TRIDENTDisable(ScrnInfoPtr pScrn);
10195b296d0Smrgstatic void	PC98TRIDENT96xxInit(ScrnInfoPtr pScrn);
10295b296d0Smrgstatic void	PC98TRIDENT96xxEnable(ScrnInfoPtr pScrn);
10395b296d0Smrgstatic void	PC98TRIDENT96xxDisable(ScrnInfoPtr pScrn);
10495b296d0Smrgstatic void	PC98TRIDENT9385Init(ScrnInfoPtr pScrn);
10595b296d0Smrgstatic void	PC98TRIDENT9385Enable(ScrnInfoPtr pScrn);
10695b296d0Smrgstatic void	PC98TRIDENT9385Disable(ScrnInfoPtr pScrn);
10795b296d0Smrgstatic int      TRIDENTLcdDisplaySize (xf86MonPtr pMon);
10895b296d0Smrg
10995b296d0Smrg/*
11095b296d0Smrg * This is intentionally screen-independent.  It indicates the binding
11195b296d0Smrg * choice made in the first PreInit.
11295b296d0Smrg */
11395b296d0Smrgstatic int pix24bpp = 0;
11495b296d0Smrg
11595b296d0Smrg#define TRIDENT_VERSION 4000
11695b296d0Smrg#define TRIDENT_NAME "TRIDENT"
11795b296d0Smrg#define TRIDENT_DRIVER_NAME "trident"
11895b296d0Smrg#define TRIDENT_MAJOR_VERSION 1
11995b296d0Smrg#define TRIDENT_MINOR_VERSION 2
12095b296d0Smrg#define TRIDENT_PATCHLEVEL 3
12195b296d0Smrg
12295b296d0Smrg/*
12395b296d0Smrg * This contains the functions needed by the server after loading the driver
12495b296d0Smrg * module.  It must be supplied, and gets passed back by the SetupProc
12595b296d0Smrg * function in the dynamic case.  In the static case, a reference to this
12695b296d0Smrg * is compiled in, and this requires that the name of this DriverRec be
12795b296d0Smrg * an upper-case version of the driver name.
12895b296d0Smrg */
12995b296d0Smrg
13095b296d0Smrg_X_EXPORT DriverRec TRIDENT = {
13195b296d0Smrg    TRIDENT_VERSION,
13295b296d0Smrg    TRIDENT_DRIVER_NAME,
13395b296d0Smrg    TRIDENTIdentify,
13495b296d0Smrg    TRIDENTProbe,
13595b296d0Smrg    TRIDENTAvailableOptions,
13695b296d0Smrg    NULL,
13795b296d0Smrg    0
13895b296d0Smrg};
13995b296d0Smrg
14095b296d0Smrgstatic SymTabRec TRIDENTChipsets[] = {
14195b296d0Smrg    { TVGA9000,			"tvga9000" },
14295b296d0Smrg    { TVGA9000i,		"tvga9000i" },
14395b296d0Smrg    { TVGA8900C,		"tvga8900c" },
14495b296d0Smrg    { TVGA8900D,		"tvga8900d" },
14595b296d0Smrg    { TVGA9200CXr,		"tvga9200cxr" },
14695b296d0Smrg    { TGUI9400CXi,		"tgui9400cxi" },
14795b296d0Smrg    { CYBER9320,		"cyber9320" },
14895b296d0Smrg    { CYBER9388,		"cyber9388" },
14995b296d0Smrg    { CYBER9397,		"cyber9397" },
15095b296d0Smrg    { CYBER9397DVD,		"cyber9397dvd" },
15195b296d0Smrg    { CYBER9520,		"cyber9520" },
15295b296d0Smrg    { CYBER9525DVD,		"cyber9525dvd" },
15395b296d0Smrg    { CYBERBLADEE4,		"cyberblade/e4" },
15495b296d0Smrg    { TGUI9420DGi,		"tgui9420dgi" },
15595b296d0Smrg    { TGUI9440AGi,		"tgui9440agi" },
15695b296d0Smrg    { TGUI9660,			"tgui9660" },
15795b296d0Smrg    { TGUI9680,			"tgui9680" },
15895b296d0Smrg    { PROVIDIA9682,		"providia9682" },
15995b296d0Smrg    { PROVIDIA9685,		"providia9685" },
16095b296d0Smrg    { CYBER9382,		"cyber9382" },
16195b296d0Smrg    { CYBER9385,		"cyber9385" },
16295b296d0Smrg    { IMAGE975,			"3dimage975" },
16395b296d0Smrg    { IMAGE985,			"3dimage985" },
16495b296d0Smrg    { BLADE3D,			"blade3d" },
16595b296d0Smrg    { CYBERBLADEI7,		"cyberbladei7" },
16695b296d0Smrg    { CYBERBLADEI7D,		"cyberbladei7d" },
16795b296d0Smrg    { CYBERBLADEI1,		"cyberbladei1" },
16895b296d0Smrg    { CYBERBLADEI1D,		"cyberbladei1d" },
16995b296d0Smrg    { CYBERBLADEAI1,		"cyberbladeAi1" },
17095b296d0Smrg    { CYBERBLADEAI1D,		"cyberbladeAi1d" },
17195b296d0Smrg    { BLADEXP,			"bladeXP" },
17295b296d0Smrg    { CYBERBLADEXPAI1,		"cyberbladeXPAi1" },
17395b296d0Smrg    { CYBERBLADEXP4,		"cyberbladeXP4" },
17495b296d0Smrg    { XP5,			"XP5" },
17595b296d0Smrg    { -1,				NULL }
17695b296d0Smrg};
17795b296d0Smrg
17895b296d0Smrgstatic IsaChipsets TRIDENTISAchipsets[] = {
17995b296d0Smrg    { TVGA9000,			RES_EXCLUSIVE_VGA },
18095b296d0Smrg    { TVGA9000i,		RES_EXCLUSIVE_VGA },
18195b296d0Smrg    { TVGA8900C,		RES_EXCLUSIVE_VGA },
18295b296d0Smrg    { TVGA8900D,		RES_EXCLUSIVE_VGA },
18395b296d0Smrg    { TVGA9200CXr,		RES_EXCLUSIVE_VGA },
18495b296d0Smrg    { TGUI9400CXi,		RES_EXCLUSIVE_VGA },
18595b296d0Smrg    { CYBER9320,		RES_EXCLUSIVE_VGA },
18695b296d0Smrg    { TGUI9440AGi,		RES_EXCLUSIVE_VGA },
18795b296d0Smrg    { -1,			RES_UNDEFINED }
18895b296d0Smrg};
18995b296d0Smrg
19095b296d0Smrgstatic PciChipsets TRIDENTPciChipsets[] = {
19195b296d0Smrg    { CYBER9320,	PCI_CHIP_9320,	RES_SHARED_VGA },
19295b296d0Smrg    { CYBER9388,	PCI_CHIP_9388,	RES_SHARED_VGA },
19395b296d0Smrg    { CYBER9397,	PCI_CHIP_9397,	RES_SHARED_VGA },
19495b296d0Smrg    { CYBER9397DVD,	PCI_CHIP_939A,	RES_SHARED_VGA },
19595b296d0Smrg    { CYBER9520,	PCI_CHIP_9520,	RES_SHARED_VGA },
19695b296d0Smrg    { CYBER9525DVD,	PCI_CHIP_9525,	RES_SHARED_VGA },
19795b296d0Smrg    { CYBERBLADEE4,	PCI_CHIP_9540,	RES_SHARED_VGA },
19895b296d0Smrg    { TGUI9420DGi,	PCI_CHIP_9420,	RES_SHARED_VGA },
19995b296d0Smrg    { TGUI9440AGi,	PCI_CHIP_9440,	RES_SHARED_VGA },
20095b296d0Smrg    { TGUI9660,		PCI_CHIP_9660,	RES_SHARED_VGA },
20195b296d0Smrg    { TGUI9680,		PCI_CHIP_9660,	RES_SHARED_VGA },
20295b296d0Smrg    { PROVIDIA9682,	PCI_CHIP_9660,	RES_SHARED_VGA },
20395b296d0Smrg    { PROVIDIA9685,	PCI_CHIP_9660,	RES_SHARED_VGA },
20495b296d0Smrg    { CYBER9382,	PCI_CHIP_9660,	RES_SHARED_VGA },
20595b296d0Smrg    { CYBER9385,	PCI_CHIP_9660,	RES_SHARED_VGA },
20695b296d0Smrg    { IMAGE975,		PCI_CHIP_9750,	RES_SHARED_VGA },
20795b296d0Smrg    { IMAGE985,		PCI_CHIP_9850,	RES_SHARED_VGA },
20895b296d0Smrg    { BLADE3D,		PCI_CHIP_9880,	RES_SHARED_VGA },
20995b296d0Smrg    { CYBERBLADEI7,	PCI_CHIP_8400,	RES_SHARED_VGA },
21095b296d0Smrg    { CYBERBLADEI7D,	PCI_CHIP_8420,	RES_SHARED_VGA },
21195b296d0Smrg    { CYBERBLADEI1,	PCI_CHIP_8500,	RES_SHARED_VGA },
21295b296d0Smrg    { CYBERBLADEI1D,	PCI_CHIP_8520,	RES_SHARED_VGA },
21395b296d0Smrg    { CYBERBLADEAI1,	PCI_CHIP_8600,	RES_SHARED_VGA },
21495b296d0Smrg    { CYBERBLADEAI1D,	PCI_CHIP_8620,	RES_SHARED_VGA },
21595b296d0Smrg    { BLADEXP,		PCI_CHIP_9910,	RES_SHARED_VGA },
21695b296d0Smrg    { CYBERBLADEXPAI1,	PCI_CHIP_8820,	RES_SHARED_VGA },
21795b296d0Smrg    { CYBERBLADEXP4,	PCI_CHIP_2100,	RES_SHARED_VGA },
21895b296d0Smrg    { XP5,		PCI_CHIP_2200,	RES_SHARED_VGA },
21995b296d0Smrg    { -1,		-1,		RES_UNDEFINED }
22095b296d0Smrg};
22195b296d0Smrg
22295b296d0Smrgtypedef enum {
22395b296d0Smrg    OPTION_ACCELMETHOD,
22495b296d0Smrg    OPTION_SW_CURSOR,
22595b296d0Smrg    OPTION_PCI_RETRY,
22695b296d0Smrg    OPTION_RGB_BITS,
22795b296d0Smrg    OPTION_NOACCEL,
22895b296d0Smrg    OPTION_SETMCLK,
22995b296d0Smrg    OPTION_MUX_THRESHOLD,
23095b296d0Smrg    OPTION_SHADOW_FB,
23195b296d0Smrg    OPTION_ROTATE,
23295b296d0Smrg    OPTION_MMIO_ONLY,
23395b296d0Smrg    OPTION_VIDEO_KEY,
23495b296d0Smrg    OPTION_NOMMIO,
23595b296d0Smrg    OPTION_NOPCIBURST,
23695b296d0Smrg    OPTION_CYBER_SHADOW,
23795b296d0Smrg    OPTION_CYBER_STRETCH,
23895b296d0Smrg    OPTION_XV_HSYNC,
23995b296d0Smrg    OPTION_XV_VSYNC,
24095b296d0Smrg    OPTION_XV_BSKEW,
24195b296d0Smrg    OPTION_XV_RSKEW,
24295b296d0Smrg    OPTION_FP_DELAY,
24395b296d0Smrg    OPTION_1400_DISPLAY,
24495b296d0Smrg    OPTION_DISPLAY,
24595b296d0Smrg    OPTION_GB,
24695b296d0Smrg    OPTION_TV_CHIPSET,
24795b296d0Smrg    OPTION_TV_SIGNALMODE
24895b296d0Smrg} TRIDENTOpts;
24995b296d0Smrg
25095b296d0Smrgstatic const OptionInfoRec TRIDENTOptions[] = {
25195b296d0Smrg    { OPTION_ACCELMETHOD,	"AccelMethod",	OPTV_ANYSTR,	{0}, FALSE },
25295b296d0Smrg    { OPTION_SW_CURSOR,		"SWcursor",	OPTV_BOOLEAN,	{0}, FALSE },
25395b296d0Smrg    { OPTION_PCI_RETRY,		"PciRetry",	OPTV_BOOLEAN,	{0}, FALSE },
25495b296d0Smrg    { OPTION_NOACCEL,		"NoAccel",	OPTV_BOOLEAN,	{0}, FALSE },
25595b296d0Smrg    { OPTION_SETMCLK,		"SetMClk",	OPTV_FREQ,	{0}, FALSE },
25695b296d0Smrg    { OPTION_MUX_THRESHOLD,	"MUXThreshold",	OPTV_INTEGER,	{0}, FALSE },
25795b296d0Smrg    { OPTION_SHADOW_FB,		"ShadowFB",	OPTV_BOOLEAN,	{0}, FALSE },
25895b296d0Smrg    { OPTION_ROTATE,  	        "Rotate",	OPTV_ANYSTR,	{0}, FALSE },
25995b296d0Smrg    { OPTION_VIDEO_KEY,		"VideoKey",	OPTV_INTEGER,	{0}, FALSE },
26095b296d0Smrg    { OPTION_NOMMIO,		"NoMMIO",	OPTV_BOOLEAN,	{0}, FALSE },
26195b296d0Smrg    { OPTION_NOPCIBURST,	"NoPciBurst",	OPTV_BOOLEAN,	{0}, FALSE },
26295b296d0Smrg    { OPTION_MMIO_ONLY,		"MMIOonly",	OPTV_BOOLEAN,	{0}, FALSE },
26395b296d0Smrg    { OPTION_CYBER_SHADOW,	"CyberShadow",	OPTV_BOOLEAN,	{0}, FALSE },
26495b296d0Smrg    { OPTION_CYBER_STRETCH,	"CyberStretch",	OPTV_BOOLEAN,	{0}, FALSE },
26595b296d0Smrg    { OPTION_XV_HSYNC,          "XvHsync",      OPTV_INTEGER,   {0}, FALSE },
26695b296d0Smrg    { OPTION_XV_VSYNC,          "XvVsync",      OPTV_INTEGER,   {0}, FALSE },
26795b296d0Smrg    { OPTION_XV_BSKEW,          "XvBskew",      OPTV_INTEGER,   {0}, FALSE },
26895b296d0Smrg    { OPTION_XV_RSKEW,          "XvRskew",      OPTV_INTEGER,   {0}, FALSE },
26995b296d0Smrg    { OPTION_FP_DELAY,          "FpDelay",      OPTV_INTEGER,   {0}, FALSE },
27095b296d0Smrg    { OPTION_1400_DISPLAY,	"Display1400",	OPTV_BOOLEAN,	{0}, FALSE },
27195b296d0Smrg    { OPTION_DISPLAY,		"Display",	OPTV_ANYSTR,	{0}, FALSE },
27295b296d0Smrg    { OPTION_GB,		"GammaBrightness",	OPTV_ANYSTR,	{0}, FALSE },
27395b296d0Smrg    { OPTION_TV_CHIPSET,        "TVChipset",    OPTV_ANYSTR,    {0}, FALSE },
27495b296d0Smrg    { OPTION_TV_SIGNALMODE,     "TVSignal",     OPTV_INTEGER,   {0}, FALSE },
27595b296d0Smrg    { -1,			NULL,		OPTV_NONE,	{0}, FALSE }
27695b296d0Smrg};
27795b296d0Smrg
27895b296d0Smrg/* Clock Limits */
27995b296d0Smrgstatic int ClockLimit[] = {
28095b296d0Smrg	80000,
28195b296d0Smrg	80000,
28295b296d0Smrg	80000,
28395b296d0Smrg	80000,
28495b296d0Smrg	80000,
28595b296d0Smrg	80000,
28695b296d0Smrg	80000,
28795b296d0Smrg	80000,
28895b296d0Smrg	80000,
28995b296d0Smrg	80000,
29095b296d0Smrg	80000,
29195b296d0Smrg	80000,
29295b296d0Smrg	80000,
29395b296d0Smrg	80000,
29495b296d0Smrg	90000,
29595b296d0Smrg	90000,
29695b296d0Smrg	135000,
29795b296d0Smrg	135000,
29895b296d0Smrg	170000,
29995b296d0Smrg	170000,
30095b296d0Smrg	170000,
30195b296d0Smrg	170000,
30295b296d0Smrg	170000,
30395b296d0Smrg	170000,
30495b296d0Smrg	170000,
30595b296d0Smrg	230000,
30695b296d0Smrg	230000,
30795b296d0Smrg	230000,
30895b296d0Smrg	230000,
30995b296d0Smrg	230000,
31095b296d0Smrg	230000,
31195b296d0Smrg	230000,
31295b296d0Smrg	230000,
31395b296d0Smrg	230000,
31495b296d0Smrg	230000,
31595b296d0Smrg	230000,
31695b296d0Smrg	230000,
31795b296d0Smrg	230000,
31895b296d0Smrg	230000,
31995b296d0Smrg	230000,
32095b296d0Smrg	230000,
32195b296d0Smrg};
32295b296d0Smrg
32395b296d0Smrgstatic int ClockLimit16bpp[] = {
32495b296d0Smrg	40000,
32595b296d0Smrg	40000,
32695b296d0Smrg	40000,
32795b296d0Smrg	40000,
32895b296d0Smrg	40000,
32995b296d0Smrg	40000,
33095b296d0Smrg	40000,
33195b296d0Smrg	40000,
33295b296d0Smrg	40000,
33395b296d0Smrg	40000,
33495b296d0Smrg	40000,
33595b296d0Smrg	40000,
33695b296d0Smrg	40000,
33795b296d0Smrg	40000,
33895b296d0Smrg	45000,
33995b296d0Smrg	45000,
34095b296d0Smrg	90000,
34195b296d0Smrg	90000,
34295b296d0Smrg	135000,
34395b296d0Smrg	135000,
34495b296d0Smrg	170000,
34595b296d0Smrg	170000,
34695b296d0Smrg	170000,
34795b296d0Smrg	170000,
34895b296d0Smrg	170000,
34995b296d0Smrg	230000,
35095b296d0Smrg	230000,
35195b296d0Smrg	230000,
35295b296d0Smrg	230000,
35395b296d0Smrg	230000,
35495b296d0Smrg	230000,
35595b296d0Smrg	230000,
35695b296d0Smrg	230000,
35795b296d0Smrg	230000,
35895b296d0Smrg	230000,
35995b296d0Smrg	230000,
36095b296d0Smrg	230000,
36195b296d0Smrg	230000,
36295b296d0Smrg	230000,
36395b296d0Smrg	230000,
36495b296d0Smrg	230000,
36595b296d0Smrg};
36695b296d0Smrg
36795b296d0Smrgstatic int ClockLimit24bpp[] = {
36895b296d0Smrg	25180,
36995b296d0Smrg	25180,
37095b296d0Smrg	25180,
37195b296d0Smrg	25180,
37295b296d0Smrg	25180,
37395b296d0Smrg	25180,
37495b296d0Smrg	25180,
37595b296d0Smrg	25180,
37695b296d0Smrg	25180,
37795b296d0Smrg	25180,
37895b296d0Smrg	25180,
37995b296d0Smrg	25180,
38095b296d0Smrg	25180,
38195b296d0Smrg	25180,
38295b296d0Smrg	25180,
38395b296d0Smrg	25180,
38495b296d0Smrg	40000,
38595b296d0Smrg	40000,
38695b296d0Smrg	70000,
38795b296d0Smrg	70000,
38895b296d0Smrg	70000,
38995b296d0Smrg	115000,
39095b296d0Smrg	115000,
39195b296d0Smrg	115000,
39295b296d0Smrg	115000,
39395b296d0Smrg	115000,
39495b296d0Smrg	115000,
39595b296d0Smrg	115000,
39695b296d0Smrg	115000,
39795b296d0Smrg	115000,
39895b296d0Smrg	115000,
39995b296d0Smrg	115000,
40095b296d0Smrg	115000,
40195b296d0Smrg	115000,
40295b296d0Smrg	115000,
40395b296d0Smrg	115000,
40495b296d0Smrg	115000,
40595b296d0Smrg	115000,
40695b296d0Smrg	115000,
40795b296d0Smrg	115000,
40895b296d0Smrg	115000,
40995b296d0Smrg};
41095b296d0Smrg
41195b296d0Smrgstatic int ClockLimit32bpp[] = {
41295b296d0Smrg	25180,
41395b296d0Smrg	25180,
41495b296d0Smrg	25180,
41595b296d0Smrg	25180,
41695b296d0Smrg	25180,
41795b296d0Smrg	25180,
41895b296d0Smrg	25180,
41995b296d0Smrg	25180,
42095b296d0Smrg	25180,
42195b296d0Smrg	25180,
42295b296d0Smrg	25180,
42395b296d0Smrg	25180,
42495b296d0Smrg	25180,
42595b296d0Smrg	25180,
42695b296d0Smrg	25180,
42795b296d0Smrg	25180,
42895b296d0Smrg	40000,
42995b296d0Smrg	40000,
43095b296d0Smrg	70000,
43195b296d0Smrg	70000,
43295b296d0Smrg	70000,
43395b296d0Smrg	115000,
43495b296d0Smrg	115000,
43595b296d0Smrg	115000,
43695b296d0Smrg	115000,
43795b296d0Smrg	115000,
43895b296d0Smrg	115000,
43995b296d0Smrg	115000,
44095b296d0Smrg	115000,
44195b296d0Smrg	115000,
44295b296d0Smrg	115000,
44395b296d0Smrg	115000,
44495b296d0Smrg	115000,
44595b296d0Smrg	115000,
44695b296d0Smrg	115000,
44795b296d0Smrg	115000,
44895b296d0Smrg	115000,
44995b296d0Smrg	115000,
45095b296d0Smrg	115000,
45195b296d0Smrg	115000,
45295b296d0Smrg	115000,
45395b296d0Smrg	115000,
45495b296d0Smrg};
45595b296d0Smrg
45695b296d0Smrg/*
45795b296d0Smrg * These are fixed modelines for all physical display dimensions the
45895b296d0Smrg *  chipsets supports on FPs. Most of them are not tested yet.
45995b296d0Smrg */
46095b296d0Smrg#if 0
46195b296d0SmrgtridentLCD LCD[] = {   /* 0    3    4    5   6    7    10   11  16 */
46295b296d0Smrg    { 0,"640x480",25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08},
46395b296d0Smrg    { 1,"800x600",40000,0x7f,0x99,0x69,0x99,0x72,0xf0,0x59,0x2d,0x5e,0x08},
46495b296d0Smrg    { 2,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08},
46595b296d0Smrg    { 3,"1024x768",65000,0xa3,/*0x6*/ 0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08}, /*0x96*/
46695b296d0Smrg    { 4,"1280x1024",108000,0xa3,0x6,0x8f,0xa0,0x24,0xf5,0x0f,0x25,0x96,0x08},
46795b296d0Smrg    { 5,"1024x600",50500 ,0xa3,0x6,0x8f,0xa0,0xb,0x3e,0xea,0x8c,0xb,0x08},
46895b296d0Smrg    { 0xff,"", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
46995b296d0Smrg};
47095b296d0Smrg#else
47195b296d0Smrg#if 0
47295b296d0SmrgtridentLCD LCD[] = {
47395b296d0Smrg    { 1,640,480,25200,0x5f,0x82,0x54,0x80,0xb,0x3e,0xea,0x8c,0xb,0x08},
47495b296d0Smrg    { 3,800,600,40000,0x7f,0x82,0x6b,0x1b,0x72,0xf8,0x58,0x8c,0x72,0x08},
47595b296d0Smrg    { 2,1024,768,65000,0xa3,/*0x6*/0x98,0x8f,0xa0,0x24,0xf5,0x0f,0x24,0x0a,0x08},
47695b296d0Smrg    { 0,1280,1024,108000,0xce,0x81,0xa6,0x9a,0x27,0x50,0x00,0x03,0x26,0xa8},
47795b296d0Smrg    { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
47895b296d0Smrg};
47995b296d0Smrg#else
48095b296d0SmrgtridentLCD LCD[] = {
48195b296d0Smrg    { 1,640,480,25200,0x5f,0x80,0x52,0x1e,0xb,0x3e,0xea,0x0c,0xb,0x08},
48295b296d0Smrg    { 3,800,600,40000,0x7f,0x00,0x69,0x7f,0x72,0xf0,0x59,0x0d,0x00,0x08},
48395b296d0Smrg    { 2,1024,768,65000,0xa3,0x00,0x84,0x94,0x24,0xf5,0x03,0x09,0x24,0x08},
48495b296d0Smrg    { 0,1280,1024,108000,0xce,0x91,0xa6,0x14,0x28,0x5a,0x01,0x04,0x28,0xa8},
48595b296d0Smrg    { 4,1400,1050,122000,0xe6,0x8d,0xba,0x1d,0x38,0x00,0x1c,0x28,0x28,0xf8},
48695b296d0Smrg    { 0xff,0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
48795b296d0Smrg};
48895b296d0Smrg#endif
48995b296d0Smrg#endif
49095b296d0Smrg
49195b296d0Smrgstatic const char *xaaSymbols[] = {
49295b296d0Smrg    "XAAGetCopyROP",
49395b296d0Smrg    "XAACreateInfoRec",
49495b296d0Smrg    "XAADestroyInfoRec",
49595b296d0Smrg    "XAAInit",
49695b296d0Smrg    "XAAGetPatternROP",
49795b296d0Smrg    NULL
49895b296d0Smrg};
49995b296d0Smrg
50095b296d0Smrgconst char *exaSymbols[] = {
50195b296d0Smrg    "exaDriverAlloc",
50295b296d0Smrg    "exaDriverInit",
50395b296d0Smrg    "exaDriverFini",
50495b296d0Smrg    "exaOffscreenAlloc",
50595b296d0Smrg    "exaOffscreenFree",
50695b296d0Smrg    NULL
50795b296d0Smrg};
50895b296d0Smrg
50995b296d0Smrgstatic const char *vgahwSymbols[] = {
51095b296d0Smrg    "vgaHWBlankScreenWeak",
51195b296d0Smrg    "vgaHWFreeHWRec",
51295b296d0Smrg    "vgaHWGetHWRec",
51395b296d0Smrg    "vgaHWGetIOBase",
51495b296d0Smrg    "vgaHWGetIndex",
51595b296d0Smrg    "vgaHWInit",
51695b296d0Smrg    "vgaHWLock",
51795b296d0Smrg    "vgaHWMapMem",
51895b296d0Smrg    "vgaHWProtectWeak",
51995b296d0Smrg    "vgaHWRestore",
52095b296d0Smrg    "vgaHWSave",
52195b296d0Smrg    "vgaHWSaveScreen",
52295b296d0Smrg    "vgaHWSetMmioFuncs",
52395b296d0Smrg    "vgaHWUnlock",
52495b296d0Smrg    NULL
52595b296d0Smrg};
52695b296d0Smrg
52795b296d0Smrgstatic const char *fbSymbols[] = {
52895b296d0Smrg    "fbPictureInit",
52995b296d0Smrg    "fbScreenInit",
53095b296d0Smrg    NULL
53195b296d0Smrg};
53295b296d0Smrg
53395b296d0Smrgstatic const char *ramdacSymbols[] = {
53495b296d0Smrg    "xf86CreateCursorInfoRec",
53595b296d0Smrg    "xf86DestroyCursorInfoRec",
53695b296d0Smrg    "xf86InitCursor",
53795b296d0Smrg    NULL
53895b296d0Smrg};
53995b296d0Smrg
54095b296d0Smrgstatic const char *ddcSymbols[] = {
54195b296d0Smrg    "xf86PrintEDID",
54295b296d0Smrg    "xf86SetDDCproperties",
54395b296d0Smrg    NULL
54495b296d0Smrg};
54595b296d0Smrg
54695b296d0Smrgstatic const char *i2cSymbols[] = {
54795b296d0Smrg    "xf86CreateI2CBusRec",
54895b296d0Smrg    "xf86I2CBusInit",
54995b296d0Smrg    NULL
55095b296d0Smrg};
55195b296d0Smrg
55295b296d0Smrgstatic const char *int10Symbols[] = {
55395b296d0Smrg    "xf86ExecX86int10",
55495b296d0Smrg    "xf86FreeInt10",
55595b296d0Smrg    "xf86InitInt10",
55695b296d0Smrg    NULL
55795b296d0Smrg};
55895b296d0Smrg
55995b296d0Smrgstatic const char *shadowSymbols[] = {
56095b296d0Smrg    "shadowInit",
56195b296d0Smrg    NULL
56295b296d0Smrg};
56395b296d0Smrg
56495b296d0Smrgstatic const char *vbeSymbols[] = {
56595b296d0Smrg    "VBEInit",
56695b296d0Smrg    "vbeDoEDID",
56795b296d0Smrg    "vbeFree",
56895b296d0Smrg    NULL
56995b296d0Smrg};
57095b296d0Smrg
57195b296d0Smrg#ifdef XFree86LOADER
57295b296d0Smrg
57395b296d0Smrgstatic MODULESETUPPROTO(tridentSetup);
57495b296d0Smrg
57595b296d0Smrgstatic XF86ModuleVersionInfo tridentVersRec =
57695b296d0Smrg{
57795b296d0Smrg	"trident",
57895b296d0Smrg	MODULEVENDORSTRING,
57995b296d0Smrg	MODINFOSTRING1,
58095b296d0Smrg	MODINFOSTRING2,
58195b296d0Smrg	XORG_VERSION_CURRENT,
58295b296d0Smrg	TRIDENT_MAJOR_VERSION, TRIDENT_MINOR_VERSION, TRIDENT_PATCHLEVEL,
58395b296d0Smrg	ABI_CLASS_VIDEODRV,			/* This is a video driver */
58495b296d0Smrg	ABI_VIDEODRV_VERSION,
58595b296d0Smrg	MOD_CLASS_VIDEODRV,
58695b296d0Smrg	{0,0,0,0}
58795b296d0Smrg};
58895b296d0Smrg
58995b296d0Smrg_X_EXPORT XF86ModuleData tridentModuleData = {
59095b296d0Smrg	&tridentVersRec,
59195b296d0Smrg	tridentSetup,
59295b296d0Smrg	NULL
59395b296d0Smrg};
59495b296d0Smrg
59595b296d0Smrgpointer
59695b296d0SmrgtridentSetup(pointer module, pointer opts, int *errmaj, int *errmin)
59795b296d0Smrg{
59895b296d0Smrg    static Bool setupDone = FALSE;
59995b296d0Smrg
60095b296d0Smrg    if (!setupDone) {
60195b296d0Smrg	setupDone = TRUE;
60295b296d0Smrg	xf86AddDriver(&TRIDENT, module, 0);
60395b296d0Smrg	LoaderRefSymLists(vgahwSymbols, fbSymbols, i2cSymbols, vbeSymbols,
60495b296d0Smrg			  ramdacSymbols, int10Symbols,
60595b296d0Smrg			  xaaSymbols, exaSymbols, shadowSymbols, NULL);
60695b296d0Smrg	return (pointer)TRUE;
60795b296d0Smrg    }
60895b296d0Smrg
60995b296d0Smrg    if (errmaj) *errmaj = LDR_ONCEONLY;
61095b296d0Smrg    return NULL;
61195b296d0Smrg}
61295b296d0Smrg
61395b296d0Smrg#endif /* XFree86LOADER */
61495b296d0Smrg
61595b296d0Smrgstatic Bool
61695b296d0SmrgTRIDENTGetRec(ScrnInfoPtr pScrn)
61795b296d0Smrg{
61895b296d0Smrg    /*
61995b296d0Smrg     * Allocate an TRIDENTRec, and hook it into pScrn->driverPrivate.
62095b296d0Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
62195b296d0Smrg     * the allocation has already been done.
62295b296d0Smrg     */
62395b296d0Smrg    if (pScrn->driverPrivate != NULL)
62495b296d0Smrg	return TRUE;
62595b296d0Smrg
62695b296d0Smrg    pScrn->driverPrivate = xnfcalloc(sizeof(TRIDENTRec), 1);
62795b296d0Smrg    /* Initialise it */
62895b296d0Smrg
62995b296d0Smrg    return TRUE;
63095b296d0Smrg}
63195b296d0Smrg
63295b296d0Smrgstatic void
63395b296d0SmrgTRIDENTFreeRec(ScrnInfoPtr pScrn)
63495b296d0Smrg{
63595b296d0Smrg    if (pScrn->driverPrivate == NULL)
63695b296d0Smrg	return;
63795b296d0Smrg    xfree(pScrn->driverPrivate);
63895b296d0Smrg    pScrn->driverPrivate = NULL;
63995b296d0Smrg}
64095b296d0Smrg
64195b296d0Smrgstatic void
64295b296d0SmrgTRIDENTDisplayPowerManagementSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags)
64395b296d0Smrg{
64495b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
64595b296d0Smrg    CARD8 DPMSCont, PMCont, temp;
64695b296d0Smrg
64795b296d0Smrg    if (!pScrn->vtSema)
64895b296d0Smrg	return;
64995b296d0Smrg
65095b296d0Smrg    OUTB(0x3C4, 0x0E);
65195b296d0Smrg    temp = INB(0x3C5);
65295b296d0Smrg    OUTB(0x3C5, 0xC2);
65395b296d0Smrg    OUTB(0x83C8, 0x04); /* Read DPMS Control */
65495b296d0Smrg    PMCont = INB(0x83C6) & 0xFC;
65595b296d0Smrg    OUTB(0x3CE, 0x23);
65695b296d0Smrg    DPMSCont = INB(0x3CF) & 0xFC;
65795b296d0Smrg    switch (PowerManagementMode)
65895b296d0Smrg    {
65995b296d0Smrg	case DPMSModeOn:
66095b296d0Smrg		/* Screen: On, HSync: On, VSync: On */
66195b296d0Smrg		PMCont |= 0x03;
66295b296d0Smrg		DPMSCont |= 0x00;
66395b296d0Smrg		break;
66495b296d0Smrg	case DPMSModeStandby:
66595b296d0Smrg		/* Screen: Off, HSync: Off, VSync: On */
66695b296d0Smrg		PMCont |= 0x02;
66795b296d0Smrg		DPMSCont |= 0x01;
66895b296d0Smrg		break;
66995b296d0Smrg	case DPMSModeSuspend:
67095b296d0Smrg		/* Screen: Off, HSync: On, VSync: Off */
67195b296d0Smrg		PMCont |= 0x02;
67295b296d0Smrg		DPMSCont |= 0x02;
67395b296d0Smrg		break;
67495b296d0Smrg	case DPMSModeOff:
67595b296d0Smrg		/* Screen: Off, HSync: Off, VSync: Off */
67695b296d0Smrg		PMCont |= 0x00;
67795b296d0Smrg		DPMSCont |= 0x03;
67895b296d0Smrg		break;
67995b296d0Smrg    }
68095b296d0Smrg    OUTB(0x3CF, DPMSCont);
68195b296d0Smrg    OUTB(0x83C8, 0x04);
68295b296d0Smrg    OUTB(0x83C6, PMCont);
68395b296d0Smrg    OUTW(0x3C4, (temp<<8) | 0x0E);
68495b296d0Smrg}
68595b296d0Smrg
68695b296d0Smrgstatic void
68795b296d0SmrgTRIDENTBlockHandler (
68895b296d0Smrg    int i,
68995b296d0Smrg    pointer     blockData,
69095b296d0Smrg    pointer     pTimeout,
69195b296d0Smrg    pointer     pReadmask
69295b296d0Smrg){
69395b296d0Smrg    ScreenPtr      pScreen = screenInfo.screens[i];
69495b296d0Smrg    ScrnInfoPtr    pScrn = xf86Screens[i];
69595b296d0Smrg    TRIDENTPtr     pTrident = TRIDENTPTR(pScrn);
69695b296d0Smrg
69795b296d0Smrg    pScreen->BlockHandler = pTrident->BlockHandler;
69895b296d0Smrg    (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
69995b296d0Smrg    pScreen->BlockHandler = TRIDENTBlockHandler;
70095b296d0Smrg
70195b296d0Smrg    if(pTrident->VideoTimerCallback) {
70295b296d0Smrg	UpdateCurrentTime();
70395b296d0Smrg	(*pTrident->VideoTimerCallback)(pScrn, currentTime.milliseconds);
70495b296d0Smrg    }
70595b296d0Smrg}
70695b296d0Smrg
70795b296d0Smrgstatic const OptionInfoRec *
70895b296d0SmrgTRIDENTAvailableOptions(int chipid, int busid)
70995b296d0Smrg{
71095b296d0Smrg    return TRIDENTOptions;
71195b296d0Smrg}
71295b296d0Smrg
71395b296d0Smrg/* Mandatory */
71495b296d0Smrgstatic void
71595b296d0SmrgTRIDENTIdentify(int flags)
71695b296d0Smrg{
71795b296d0Smrg    xf86PrintChipsets(TRIDENT_NAME, "driver for Trident chipsets", TRIDENTChipsets);
71895b296d0Smrg}
71995b296d0Smrg
72095b296d0SmrgBool
72195b296d0SmrgTRIDENTClockSelect(ScrnInfoPtr pScrn, int no)
72295b296d0Smrg{
72395b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
72495b296d0Smrg    unsigned char temp;
72595b296d0Smrg
72695b296d0Smrg    /*
72795b296d0Smrg     * CS0 and CS1 are in MiscOutReg
72895b296d0Smrg     *
72995b296d0Smrg     * For 8900B, 8900C, 8900CL and 9000, CS2 is bit 0 of
73095b296d0Smrg     * New Mode Control Register 2.
73195b296d0Smrg     *
73295b296d0Smrg     * For 8900CL, CS3 is bit 4 of Old Mode Control Register 1.
73395b296d0Smrg     *
73495b296d0Smrg     * For 9000, CS3 is bit 6 of New Mode Control Register 2.
73595b296d0Smrg     *
73695b296d0Smrg     * For TGUI, we don't use the ClockSelect function at all.
73795b296d0Smrg     */
73895b296d0Smrg     switch(no) {
73995b296d0Smrg	case CLK_REG_SAVE:
74095b296d0Smrg	    pTrident->SaveClock1 = INB(0x3CC);
74195b296d0Smrg	    if (pTrident->Chipset != TVGA8800CS) {
74295b296d0Smrg		if ( (pScrn->numClocks == 16) &&
74395b296d0Smrg		     (pTrident->Chipset != TVGA9000) &&
74495b296d0Smrg		     (pTrident->Chipset != TVGA9000i) )
74595b296d0Smrg		{
74695b296d0Smrg		    OUTW(0x3C4, 0x000B);	/* Switch to Old Mode */
74795b296d0Smrg		    OUTB(0x3C4, 0x0E); pTrident->SaveClock3 = INB(0x3C5);
74895b296d0Smrg		}
74995b296d0Smrg		OUTB(0x3C4, 0x0B);
75095b296d0Smrg		INB(0x3C5);		/* Now to New Mode */
75195b296d0Smrg		OUTB(0x3C4, 0x0D); pTrident->SaveClock2 = INB(0x3C5);
75295b296d0Smrg	    }
75395b296d0Smrg	    break;
75495b296d0Smrg	case CLK_REG_RESTORE:
75595b296d0Smrg	    OUTB(0x3C2, pTrident->SaveClock1);
75695b296d0Smrg	    if (pTrident->Chipset != TVGA8800CS) {
75795b296d0Smrg		if ( (pScrn->numClocks == 16) &&
75895b296d0Smrg		     (pTrident->Chipset != TVGA9000) &&
75995b296d0Smrg		     (pTrident->Chipset != TVGA9000i) )
76095b296d0Smrg		{
76195b296d0Smrg			OUTW(0x3C4, 0x000B);	/* Switch to Old Mode */
76295b296d0Smrg			OUTW(0x3C4, (pTrident->SaveClock3 << 8) | 0x0E);
76395b296d0Smrg		}
76495b296d0Smrg		OUTB(0x3C4, 0x0B);
76595b296d0Smrg		INB(0x3C5);		/* Now to New Mode */
76695b296d0Smrg		OUTW(0x3C4, (pTrident->SaveClock2 << 8) | 0x0D);
76795b296d0Smrg	    }
76895b296d0Smrg	    break;
76995b296d0Smrg	default:
77095b296d0Smrg	    /*
77195b296d0Smrg	     * Do CS0 and CS1
77295b296d0Smrg	     */
77395b296d0Smrg	    temp = INB(0x3CC);
77495b296d0Smrg	    OUTB(0x3C2, (temp & 0xF3) | ((no << 2) & 0x0C));
77595b296d0Smrg	    if (pTrident->Chipset != TVGA8800CS) {
77695b296d0Smrg		if ( (pScrn->numClocks == 16) &&
77795b296d0Smrg		     (pTrident->Chipset != TVGA9000) &&
77895b296d0Smrg		     (pTrident->Chipset != TVGA9000i) )
77995b296d0Smrg		{
78095b296d0Smrg			/*
78195b296d0Smrg			 * Go to Old Mode for CS3.
78295b296d0Smrg		 	 */
78395b296d0Smrg			OUTW(0x3C4, 0x000B);	/* Switch to Old Mode */
78495b296d0Smrg			OUTB(0x3C4, 0x0E);
78595b296d0Smrg			temp = INB(0x3C5) & 0xEF;
78695b296d0Smrg			temp |= (no & 0x08) << 1;
78795b296d0Smrg			OUTB(0x3C5, temp);
78895b296d0Smrg		}
78995b296d0Smrg		/*
79095b296d0Smrg	  	 * Go to New Mode for CS2 and TVGA9000 CS3.
79195b296d0Smrg	  	 */
79295b296d0Smrg		OUTB(0x3C4, 0x0B);
79395b296d0Smrg		INB(0x3C5);		/* Now to New Mode */
79495b296d0Smrg		OUTB(0x3C4, 0x0D);
79595b296d0Smrg		/*
79695b296d0Smrg		 * Bits 1 & 2 are dividers - set to 0 to get no
79795b296d0Smrg		 * clock division.
79895b296d0Smrg		 */
79995b296d0Smrg		temp = INB(0x3C5) & 0xF8;
80095b296d0Smrg		temp |= (no & 0x04) >> 2;
80195b296d0Smrg		if ( (pTrident->Chipset == TVGA9000) ||
80295b296d0Smrg		     (pTrident->Chipset == TVGA9000i) )
80395b296d0Smrg		{
80495b296d0Smrg			temp &= ~0x40;
80595b296d0Smrg			temp |= (no & 0x08) << 3;
80695b296d0Smrg		}
80795b296d0Smrg		OUTB(0x3C5, temp);
80895b296d0Smrg	}
80995b296d0Smrg    }
81095b296d0Smrg    return(TRUE);
81195b296d0Smrg}
81295b296d0Smrg
81395b296d0Smrgstatic int
81495b296d0SmrgTridentFindIsaDevice(GDevPtr dev)
81595b296d0Smrg{
81695b296d0Smrg    int found = -1;
81795b296d0Smrg    unsigned char temp, origVal, newVal;
81895b296d0Smrg
81995b296d0Smrg    /*
82095b296d0Smrg     * Check first that we have a Trident card.
82195b296d0Smrg     */
82295b296d0Smrg    outb(0x3C4, 0x0B);
82395b296d0Smrg    temp = inb(0x3C5);	/* Save old value */
82495b296d0Smrg    outb(0x3C4, 0x0B);	/* Switch to Old Mode */
82595b296d0Smrg    outb(0x3C5, 0x00);
82695b296d0Smrg    inb(0x3C5);		/* Now to New Mode */
82795b296d0Smrg    outb(0x3C4, 0x0E);
82895b296d0Smrg    origVal = inb(0x3C5);
82995b296d0Smrg    outb(0x3C5, 0x00);
83095b296d0Smrg    newVal = inb(0x3C5) & 0x0F;
83195b296d0Smrg    outb(0x3C5, (origVal ^ 0x02));
83295b296d0Smrg
83395b296d0Smrg    /*
83495b296d0Smrg     * Is it a Trident card ??
83595b296d0Smrg     */
83695b296d0Smrg    if (newVal != 2) {
83795b296d0Smrg	/*
83895b296d0Smrg	 * Nope, so quit
83995b296d0Smrg	 */
84095b296d0Smrg	outb(0x3C4, 0x0B);	/* Restore value of 0x0B */
84195b296d0Smrg	outb(0x3C5, temp);
84295b296d0Smrg	outb(0x3C4, 0x0E);
84395b296d0Smrg	outb(0x3C5, origVal);
84495b296d0Smrg	return found;
84595b296d0Smrg    }
84695b296d0Smrg
84795b296d0Smrg    outb(0x3C4, 0x0B);
84895b296d0Smrg    temp = inb(0x3C5);
84995b296d0Smrg    switch (temp) {
85095b296d0Smrg	case 0x01:
85195b296d0Smrg	    found = TVGA8800BR;
85295b296d0Smrg	    break;
85395b296d0Smrg	case 0x02:
85495b296d0Smrg	    found = TVGA8800CS;
85595b296d0Smrg	    break;
85695b296d0Smrg	case 0x03:
85795b296d0Smrg	    found = TVGA8900B;
85895b296d0Smrg	    break;
85995b296d0Smrg	case 0x04:
86095b296d0Smrg	case 0x13:
86195b296d0Smrg	    found = TVGA8900C;
86295b296d0Smrg	    break;
86395b296d0Smrg	case 0x23:
86495b296d0Smrg	    found = TVGA9000;
86595b296d0Smrg	    break;
86695b296d0Smrg	case 0x33:
86795b296d0Smrg	    found = TVGA8900D;
86895b296d0Smrg	    break;
86995b296d0Smrg	case 0x43:
87095b296d0Smrg	    found = TVGA9000i;
87195b296d0Smrg	    break;
87295b296d0Smrg	case 0x53:
87395b296d0Smrg	    found = TVGA9200CXr;
87495b296d0Smrg	    break;
87595b296d0Smrg	case 0x63:
87695b296d0Smrg	    found = TVGA9100B;
87795b296d0Smrg	    break;
87895b296d0Smrg	case 0x73:
87995b296d0Smrg	case 0xC3:
88095b296d0Smrg	    found = TGUI9420DGi;
88195b296d0Smrg	    break;
88295b296d0Smrg	case 0x83:
88395b296d0Smrg	    found = TVGA8200LX;
88495b296d0Smrg	    break;
88595b296d0Smrg	case 0x93:
88695b296d0Smrg	    found = TGUI9400CXi;
88795b296d0Smrg	    break;
88895b296d0Smrg	case 0xA3:
88995b296d0Smrg	    found = CYBER9320;
89095b296d0Smrg	    break;
89195b296d0Smrg	case 0xD3:
89295b296d0Smrg	    found = TGUI9660;
89395b296d0Smrg	    break;
89495b296d0Smrg	case 0xE3:
89595b296d0Smrg	    found = TGUI9440AGi;
89695b296d0Smrg	    break;
89795b296d0Smrg	case 0xF3:
89895b296d0Smrg	    found = TGUI9430DGi;
89995b296d0Smrg	    break;
90095b296d0Smrg    }
90195b296d0Smrg    return found;
90295b296d0Smrg}
90395b296d0Smrg
90495b296d0Smrg
90595b296d0Smrg/* Mandatory */
90695b296d0Smrgstatic Bool
90795b296d0SmrgTRIDENTProbe(DriverPtr drv, int flags)
90895b296d0Smrg{
90995b296d0Smrg    int i;
91095b296d0Smrg    GDevPtr *devSections;
91195b296d0Smrg    int *usedChips = NULL;
91295b296d0Smrg    int numDevSections;
91395b296d0Smrg    int numUsed;
91495b296d0Smrg    Bool foundScreen = FALSE;
91595b296d0Smrg
91695b296d0Smrg    if ((numDevSections = xf86MatchDevice(TRIDENT_DRIVER_NAME,
91795b296d0Smrg					  &devSections)) <= 0) {
91895b296d0Smrg	/*
91995b296d0Smrg	 * There's no matching device section in the config file, so quit
92095b296d0Smrg	 * now.
92195b296d0Smrg	 */
92295b296d0Smrg	return FALSE;
92395b296d0Smrg    }
92495b296d0Smrg
92595b296d0Smrg    /*
92695b296d0Smrg     * While we're VGA-dependent, can really only have one such instance, but
92795b296d0Smrg     * we'll ignore that.
92895b296d0Smrg     */
92995b296d0Smrg
93095b296d0Smrg    /*
93195b296d0Smrg     * We need to probe the hardware first.  We then need to see how this
93295b296d0Smrg     * fits in with what is given in the config file, and allow the config
93395b296d0Smrg     * file info to override any contradictions.
93495b296d0Smrg     */
93595b296d0Smrg
93695b296d0Smrg    /*
93795b296d0Smrg     * All of the cards this driver supports are PCI, so the "probing" just
93895b296d0Smrg     * amounts to checking the PCI data that the server has already collected.
93995b296d0Smrg     */
94095b296d0Smrg    if (xf86GetPciVideoInfo()) {
94195b296d0Smrg    	numUsed = xf86MatchPciInstances(TRIDENT_NAME, PCI_VENDOR_TRIDENT,
94295b296d0Smrg		   TRIDENTChipsets, TRIDENTPciChipsets, devSections,
94395b296d0Smrg		   numDevSections, drv, &usedChips);
94495b296d0Smrg
94595b296d0Smrg	if (numUsed > 0) {
94695b296d0Smrg	    if (flags & PROBE_DETECT)
94795b296d0Smrg		foundScreen = TRUE;
94895b296d0Smrg	    else for (i = 0; i < numUsed; i++) {
94995b296d0Smrg		ScrnInfoPtr pScrn = NULL;
95095b296d0Smrg
95195b296d0Smrg		if ((pScrn = xf86ConfigPciEntity(pScrn, 0,usedChips[i],
95295b296d0Smrg						       TRIDENTPciChipsets, NULL,
95395b296d0Smrg						       NULL, NULL, NULL, NULL))) {
95495b296d0Smrg		    /* Fill in what we can of the ScrnInfoRec */
95595b296d0Smrg		    pScrn->driverVersion = TRIDENT_VERSION;
95695b296d0Smrg		    pScrn->driverName	 = TRIDENT_DRIVER_NAME;
95795b296d0Smrg		    pScrn->name		 = TRIDENT_NAME;
95895b296d0Smrg		    pScrn->Probe	 = TRIDENTProbe;
95995b296d0Smrg		    pScrn->PreInit	 = TRIDENTPreInit;
96095b296d0Smrg		    pScrn->ScreenInit	 = TRIDENTScreenInit;
96195b296d0Smrg		    pScrn->SwitchMode	 = TRIDENTSwitchMode;
96295b296d0Smrg		    pScrn->AdjustFrame	 = TRIDENTAdjustFrame;
96395b296d0Smrg		    pScrn->EnterVT	 = TRIDENTEnterVT;
96495b296d0Smrg		    pScrn->LeaveVT	 = TRIDENTLeaveVT;
96595b296d0Smrg		    pScrn->FreeScreen	 = TRIDENTFreeScreen;
96695b296d0Smrg		    pScrn->ValidMode	 = TRIDENTValidMode;
96795b296d0Smrg		    foundScreen = TRUE;
96895b296d0Smrg		}
96995b296d0Smrg	    }
97095b296d0Smrg	    xfree(usedChips);
97195b296d0Smrg	}
97295b296d0Smrg    }
97395b296d0Smrg
97495b296d0Smrg    /* Isa Bus */
97595b296d0Smrg    numUsed = xf86MatchIsaInstances(TRIDENT_NAME,TRIDENTChipsets,
97695b296d0Smrg				     TRIDENTISAchipsets,
97795b296d0Smrg				     drv,TridentFindIsaDevice,devSections,
97895b296d0Smrg				     numDevSections,&usedChips);
97995b296d0Smrg    if (numUsed > 0) {
98095b296d0Smrg	if (flags & PROBE_DETECT)
98195b296d0Smrg	    foundScreen = TRUE;
98295b296d0Smrg	else 	for (i = 0; i < numUsed; i++) {
98395b296d0Smrg	    ScrnInfoPtr pScrn = NULL;
98495b296d0Smrg	    if ((pScrn = xf86ConfigIsaEntity(pScrn,0,usedChips[i],
98595b296d0Smrg						  TRIDENTISAchipsets,NULL,
98695b296d0Smrg						  NULL,NULL,NULL,NULL))) {
98795b296d0Smrg		pScrn->driverVersion = TRIDENT_VERSION;
98895b296d0Smrg		pScrn->driverName    = TRIDENT_DRIVER_NAME;
98995b296d0Smrg		pScrn->name          = TRIDENT_NAME;
99095b296d0Smrg		pScrn->Probe         = TRIDENTProbe;
99195b296d0Smrg		pScrn->PreInit       = TRIDENTPreInit;
99295b296d0Smrg		pScrn->ScreenInit    = TRIDENTScreenInit;
99395b296d0Smrg		pScrn->SwitchMode    = TRIDENTSwitchMode;
99495b296d0Smrg		pScrn->AdjustFrame   = TRIDENTAdjustFrame;
99595b296d0Smrg		pScrn->EnterVT       = TRIDENTEnterVT;
99695b296d0Smrg		pScrn->LeaveVT       = TRIDENTLeaveVT;
99795b296d0Smrg		pScrn->FreeScreen    = TRIDENTFreeScreen;
99895b296d0Smrg		pScrn->ValidMode     = TRIDENTValidMode;
99995b296d0Smrg		foundScreen = TRUE;
100095b296d0Smrg	    }
100195b296d0Smrg	}
100295b296d0Smrg	xfree(usedChips);
100395b296d0Smrg    }
100495b296d0Smrg
100595b296d0Smrg    xfree(devSections);
100695b296d0Smrg    return foundScreen;
100795b296d0Smrg}
100895b296d0Smrg
100995b296d0Smrg/*
101095b296d0Smrg * GetAccelPitchValues -
101195b296d0Smrg *
101295b296d0Smrg * This function returns a list of display width (pitch) values that can
101395b296d0Smrg * be used in accelerated mode.
101495b296d0Smrg */
101595b296d0Smrgstatic int *
101695b296d0SmrgGetAccelPitchValues(ScrnInfoPtr pScrn)
101795b296d0Smrg{
101895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
101995b296d0Smrg    int *linePitches = NULL;
102095b296d0Smrg    int lines[4] = { 512, 1024, 2048, 4096 }; /* 9440AGi */
102195b296d0Smrg    int i, n = 0;
102295b296d0Smrg
102395b296d0Smrg    if (pTrident->Chipset >= BLADEXP) {
102495b296d0Smrg	lines[0] = 1024;
102595b296d0Smrg	lines[1] = 2048;
102695b296d0Smrg	lines[2] = 4096;
102795b296d0Smrg	lines[3] = 8192;
102895b296d0Smrg    }
102995b296d0Smrg
103095b296d0Smrg    for (i = 0; i < 4; i++) {
103195b296d0Smrg	n++;
103295b296d0Smrg	linePitches = xnfrealloc(linePitches, n * sizeof(int));
103395b296d0Smrg	linePitches[n - 1] = lines[i];
103495b296d0Smrg    }
103595b296d0Smrg
103695b296d0Smrg    /* Mark the end of the list */
103795b296d0Smrg    if (n > 0) {
103895b296d0Smrg	linePitches = xnfrealloc(linePitches, (n + 1) * sizeof(int));
103995b296d0Smrg	linePitches[n] = 0;
104095b296d0Smrg    }
104195b296d0Smrg    return linePitches;
104295b296d0Smrg}
104395b296d0Smrg
104495b296d0Smrgstatic void
104595b296d0SmrgTRIDENTProbeDDC(ScrnInfoPtr pScrn, int index)
104695b296d0Smrg{
104795b296d0Smrg    vbeInfoPtr pVbe;
104895b296d0Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
104995b296d0Smrg	pVbe = VBEInit(NULL,index);
105095b296d0Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
105195b296d0Smrg	vbeFree(pVbe);
105295b296d0Smrg    }
105395b296d0Smrg}
105495b296d0Smrg
105595b296d0Smrg/* Mandatory */
105695b296d0Smrgstatic Bool
105795b296d0SmrgTRIDENTPreInit(ScrnInfoPtr pScrn, int flags)
105895b296d0Smrg{
105995b296d0Smrg    TRIDENTPtr pTrident;
106095b296d0Smrg    vgaHWPtr hwp;
106195b296d0Smrg    MessageType from;
106295b296d0Smrg    CARD8 videoram, videorammask;
106395b296d0Smrg    char *ramtype = NULL, *chipset = NULL;
106495b296d0Smrg    Bool Support24bpp;
106595b296d0Smrg    int vgaIOBase;
106695b296d0Smrg    float mclk;
106795b296d0Smrg    double real;
106895b296d0Smrg    int i, NoClocks = 16;
106995b296d0Smrg    CARD8 revision;
107095b296d0Smrg    ClockRangePtr clockRanges;
107195b296d0Smrg    Bool ddcLoaded = FALSE;
107295b296d0Smrg    xf86MonPtr pMon = NULL;
107395b296d0Smrg    char *s;
107495b296d0Smrg    Bool tmp_bool;
107595b296d0Smrg
107695b296d0Smrg    /* Allocate the TRIDENTRec driverPrivate */
107795b296d0Smrg    if (!TRIDENTGetRec(pScrn)) {
107895b296d0Smrg	return FALSE;
107995b296d0Smrg    }
108095b296d0Smrg    pTrident = TRIDENTPTR(pScrn);
108195b296d0Smrg    pTrident->pScrn = pScrn;
108295b296d0Smrg
108395b296d0Smrg    if (pScrn->numEntities > 1)
108495b296d0Smrg	return FALSE;
108595b296d0Smrg    /* This is the general case */
108695b296d0Smrg    for (i = 0; i<pScrn->numEntities; i++) {
108795b296d0Smrg	pTrident->pEnt = xf86GetEntityInfo(pScrn->entityList[i]);
108895b296d0Smrg	if (pTrident->pEnt->resources) return FALSE;
108995b296d0Smrg	pTrident->Chipset = pTrident->pEnt->chipset;
109095b296d0Smrg	pScrn->chipset = (char *)xf86TokenToString(TRIDENTChipsets,
109195b296d0Smrg						   pTrident->pEnt->chipset);
109295b296d0Smrg	/* This driver can handle ISA and PCI buses */
109395b296d0Smrg	if (pTrident->pEnt->location.type == BUS_PCI) {
109495b296d0Smrg	    pTrident->PciInfo = xf86GetPciInfoForEntity(pTrident->pEnt->index);
109595b296d0Smrg	    pTrident->PciTag = pciTag(pTrident->PciInfo->bus,
109695b296d0Smrg				  pTrident->PciInfo->device,
109795b296d0Smrg				  pTrident->PciInfo->func);
109895b296d0Smrg    	    pTrident->Linear = TRUE;
109995b296d0Smrg	} else {
110095b296d0Smrg    	    pTrident->Linear = FALSE;
110195b296d0Smrg	}
110295b296d0Smrg    }
110395b296d0Smrg
110495b296d0Smrg    if (flags & PROBE_DETECT) {
110595b296d0Smrg	TRIDENTProbeDDC(pScrn, pTrident->pEnt->index);
110695b296d0Smrg	return TRUE;
110795b296d0Smrg    }
110895b296d0Smrg
110995b296d0Smrg    /* Set pScrn->monitor */
111095b296d0Smrg    pScrn->monitor = pScrn->confScreen->monitor;
111195b296d0Smrg
111295b296d0Smrg    /*
111395b296d0Smrg     * The first thing we should figure out is the depth, bpp, etc.
111495b296d0Smrg     * Our preference for depth 24 is 24bpp, so tell it that too.
111595b296d0Smrg     */
111695b296d0Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support24bppFb | Support32bppFb |
111795b296d0Smrg			    SupportConvert32to24 /*| PreferConvert32to24*/)) {
111895b296d0Smrg	return FALSE;
111995b296d0Smrg    } else {
112095b296d0Smrg	/* Check that the returned depth is one we support */
112195b296d0Smrg	switch (pScrn->depth) {
112295b296d0Smrg	case 8:
112395b296d0Smrg	    if (pScrn->bitsPerPixel != pScrn->depth) {
112495b296d0Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
112595b296d0Smrg	     "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n",
112695b296d0Smrg		       pScrn->depth, pScrn->bitsPerPixel);
112795b296d0Smrg		return FALSE;
112895b296d0Smrg	    }
112995b296d0Smrg	    break;
113095b296d0Smrg	case 15:
113195b296d0Smrg	case 16:
113295b296d0Smrg	    if (pScrn->bitsPerPixel != 16) {
113395b296d0Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
113495b296d0Smrg	     "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n",
113595b296d0Smrg		       pScrn->depth, pScrn->bitsPerPixel);
113695b296d0Smrg		return FALSE;
113795b296d0Smrg	    }
113895b296d0Smrg	    break;
113995b296d0Smrg	case 24:
114095b296d0Smrg	    if ((pScrn->bitsPerPixel != 24) && (pScrn->bitsPerPixel != 32)) {
114195b296d0Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
114295b296d0Smrg	     "Given depth (%d)/ fbbpp (%d) is not supported by this driver\n",
114395b296d0Smrg		       pScrn->depth, pScrn->bitsPerPixel);
114495b296d0Smrg		return FALSE;
114595b296d0Smrg	    }
114695b296d0Smrg	    /* OK */
114795b296d0Smrg	    break;
114895b296d0Smrg	default:
114995b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
115095b296d0Smrg		       "Given depth (%d) is not supported by this driver\n",
115195b296d0Smrg		       pScrn->depth);
115295b296d0Smrg	    return FALSE;
115395b296d0Smrg	}
115495b296d0Smrg    }
115595b296d0Smrg
115695b296d0Smrg    xf86PrintDepthBpp(pScrn);
115795b296d0Smrg
115895b296d0Smrg    /* Get the depth24 pixmap format */
115995b296d0Smrg    if (pScrn->depth == 24 && pix24bpp == 0)
116095b296d0Smrg	pix24bpp = xf86GetBppFromDepth(pScrn, 24);
116195b296d0Smrg
116295b296d0Smrg    /* The vgahw module should be loaded here when needed */
116395b296d0Smrg    if (!xf86LoadSubModule(pScrn, "vgahw"))
116495b296d0Smrg	return FALSE;
116595b296d0Smrg
116695b296d0Smrg    xf86LoaderReqSymLists(vgahwSymbols, NULL);
116795b296d0Smrg
116895b296d0Smrg    /*
116995b296d0Smrg     * Allocate a vgaHWRec
117095b296d0Smrg     */
117195b296d0Smrg    if (!vgaHWGetHWRec(pScrn))
117295b296d0Smrg	return FALSE;
117395b296d0Smrg
117495b296d0Smrg    hwp = VGAHWPTR(pScrn);
117595b296d0Smrg    vgaHWGetIOBase(hwp);
117695b296d0Smrg    vgaIOBase = hwp->IOBase;
117795b296d0Smrg    pTrident->PIOBase = hwp->PIOOffset;
117895b296d0Smrg
117995b296d0Smrg    xf86SetOperatingState(resVga, pTrident->pEnt->index, ResUnusedOpr);
118095b296d0Smrg
118195b296d0Smrg    /* The ramdac module should be loaded here when needed */
118295b296d0Smrg    if (!xf86LoadSubModule(pScrn, "ramdac"))
118395b296d0Smrg	return FALSE;
118495b296d0Smrg
118595b296d0Smrg    xf86LoaderReqSymLists(ramdacSymbols, NULL);
118695b296d0Smrg
118795b296d0Smrg    /*
118895b296d0Smrg     * This must happen after pScrn->display has been set because
118995b296d0Smrg     * xf86SetWeight references it.
119095b296d0Smrg     */
119195b296d0Smrg    if (pScrn->depth > 8) {
119295b296d0Smrg	/* The defaults are OK for us */
119395b296d0Smrg	rgb zeros = {0, 0, 0};
119495b296d0Smrg
119595b296d0Smrg	if (!xf86SetWeight(pScrn, zeros, zeros)) {
119695b296d0Smrg	    return FALSE;
119795b296d0Smrg	} else {
119895b296d0Smrg	    /* XXX check that weight returned is supported */
119995b296d0Smrg            ;
120095b296d0Smrg        }
120195b296d0Smrg    }
120295b296d0Smrg
120395b296d0Smrg    if (!xf86SetDefaultVisual(pScrn, -1)) {
120495b296d0Smrg	return FALSE;
120595b296d0Smrg    } else {
120695b296d0Smrg	/* We don't currently support DirectColor at > 8bpp */
120795b296d0Smrg	if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
120895b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual"
120995b296d0Smrg		       " (%s) is not supported at depth %d\n",
121095b296d0Smrg		       xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
121195b296d0Smrg	    return FALSE;
121295b296d0Smrg	}
121395b296d0Smrg    }
121495b296d0Smrg
121595b296d0Smrg    /*
121695b296d0Smrg     * The new cmap layer needs this to be initialised.
121795b296d0Smrg     */
121895b296d0Smrg
121995b296d0Smrg    {
122095b296d0Smrg	Gamma zeros = {0.0, 0.0, 0.0};
122195b296d0Smrg
122295b296d0Smrg	if (!xf86SetGamma(pScrn, zeros)) {
122395b296d0Smrg	    return FALSE;
122495b296d0Smrg	}
122595b296d0Smrg    }
122695b296d0Smrg
122795b296d0Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
122895b296d0Smrg    xf86CollectOptions(pScrn, NULL);
122995b296d0Smrg
123095b296d0Smrg    /* Process the options */
123195b296d0Smrg    if (!(pTrident->Options = xalloc(sizeof(TRIDENTOptions))))
123295b296d0Smrg	return FALSE;
123395b296d0Smrg    memcpy(pTrident->Options, TRIDENTOptions, sizeof(TRIDENTOptions));
123495b296d0Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pTrident->Options);
123595b296d0Smrg
123695b296d0Smrg    /* Set the bits per RGB for 8bpp mode */
123795b296d0Smrg    if (pScrn->depth == 8) {
123895b296d0Smrg	/* XXX This is here just to test options. */
123995b296d0Smrg	/* Default to 8 */
124095b296d0Smrg	pScrn->rgbBits = 6;
124195b296d0Smrg#if 0
124295b296d0Smrg	if (xf86GetOptValInteger(pTrident->Options, OPTION_RGB_BITS,
124395b296d0Smrg				 &pScrn->rgbBits)) {
124495b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Bits per RGB set to %d\n",
124595b296d0Smrg		       pScrn->rgbBits);
124695b296d0Smrg	}
124795b296d0Smrg#endif
124895b296d0Smrg    }
124995b296d0Smrg    from = X_DEFAULT;
125095b296d0Smrg
125195b296d0Smrg    pTrident->useEXA = FALSE;
125295b296d0Smrg    if ((s = (char *)xf86GetOptValString(pTrident->Options,
125395b296d0Smrg					 OPTION_ACCELMETHOD))) {
125495b296d0Smrg	if (!xf86NameCmp(s, "EXA")) {
125595b296d0Smrg	    pTrident->useEXA = TRUE;
125695b296d0Smrg	    from = X_CONFIG;
125795b296d0Smrg	}
125895b296d0Smrg	else if (!xf86NameCmp(s, "XAA")) {
125995b296d0Smrg	    pTrident->useEXA = FALSE;
126095b296d0Smrg	    from = X_CONFIG;
126195b296d0Smrg	}
126295b296d0Smrg    }
126395b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s for acceleration\n",
126495b296d0Smrg	       pTrident->useEXA ? "EXA" : "XAA");
126595b296d0Smrg
126695b296d0Smrg    pTrident->HWCursor = TRUE;
126795b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_SW_CURSOR, FALSE)) {
126895b296d0Smrg	from = X_CONFIG;
126995b296d0Smrg	pTrident->HWCursor = FALSE;
127095b296d0Smrg    }
127195b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOACCEL, FALSE)) {
127295b296d0Smrg	pTrident->NoAccel = TRUE;
127395b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Acceleration disabled\n");
127495b296d0Smrg    }
127595b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_PCI_RETRY, FALSE)) {
127695b296d0Smrg	pTrident->UsePCIRetry = TRUE;
127795b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry enabled\n");
127895b296d0Smrg    }
127995b296d0Smrg    pTrident->UsePCIBurst = TRUE;
128095b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOPCIBURST, FALSE)) {
128195b296d0Smrg	pTrident->UsePCIBurst = FALSE;
128295b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI Burst disbled\n");
128395b296d0Smrg    }
128495b296d0Smrg    /* Display Size override moved to DDC section */
128595b296d0Smrg    if(xf86GetOptValInteger(pTrident->Options, OPTION_VIDEO_KEY,
128695b296d0Smrg						&(pTrident->videoKey))) {
128795b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "video key set to 0x%x\n",
128895b296d0Smrg							pTrident->videoKey);
128995b296d0Smrg    } else {
129095b296d0Smrg	pTrident->videoKey =  (1 << pScrn->offset.red) |
129195b296d0Smrg			(1 << pScrn->offset.green) |
129295b296d0Smrg			(((pScrn->mask.blue >> pScrn->offset.blue) - 1)
129395b296d0Smrg			<< pScrn->offset.blue);
129495b296d0Smrg    }
129595b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_NOMMIO, FALSE)) {
129695b296d0Smrg	pTrident->NoMMIO = TRUE;
129795b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO Disabled\n");
129895b296d0Smrg    }
129995b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_MMIO_ONLY, FALSE)) {
130095b296d0Smrg	if (pTrident->NoMMIO)
130195b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "MMIO only cannot be set"
130295b296d0Smrg		       " with NoMMIO\n");
130395b296d0Smrg	else {
130495b296d0Smrg	    pTrident->MMIOonly = TRUE;
130595b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MMIO only enabled\n");
130695b296d0Smrg	}
130795b296d0Smrg    }
130895b296d0Smrg
130995b296d0Smrg    pTrident->dspOverride = 0;
131095b296d0Smrg    if ((s = xf86GetOptValString(pTrident->Options, OPTION_DISPLAY))) {
131195b296d0Smrg	if(!xf86NameCmp(s, "CRT")) {
131295b296d0Smrg	    pTrident->dspOverride = CRT_ACTIVE;
131395b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD off CRT on\n");
131495b296d0Smrg	} else if (!xf86NameCmp(s, "LCD")) {
131595b296d0Smrg	    pTrident->dspOverride = LCD_ACTIVE;
131695b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT off\n");
131795b296d0Smrg	} else if (!xf86NameCmp(s, "Dual")) {
131895b296d0Smrg	    pTrident->dspOverride = LCD_ACTIVE | CRT_ACTIVE;
131995b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"LCD on CRT on\n");
132095b296d0Smrg	} else
132195b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_ERROR,
132295b296d0Smrg		       "%s is an unknown display option\n",s);
132395b296d0Smrg    }
132495b296d0Smrg    if ((s = xf86GetOptValString(pTrident->Options, OPTION_GB))) {
132595b296d0Smrg	int brightness = -1;
132695b296d0Smrg	double gamma = -1.0;
132795b296d0Smrg	Bool error = FALSE;
132895b296d0Smrg	int i;
132995b296d0Smrg
133095b296d0Smrg	i = sscanf(s,"%lf %i",&gamma,&brightness);
133195b296d0Smrg
133295b296d0Smrg	if (i != 2 || brightness == -1 || gamma == -1.0) {
133395b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
133495b296d0Smrg		       "Invalid Gamma/Brightness argument: %s\n",s);
133595b296d0Smrg	    error = TRUE;
133695b296d0Smrg	} else {
133795b296d0Smrg	    if (brightness < 0 || brightness > 128) {
133895b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
133995b296d0Smrg			   "brightness out of range [0,128]: %i\n",brightness);
134095b296d0Smrg		error = TRUE;
134195b296d0Smrg	    }
134295b296d0Smrg	    if (gamma <= 0.0 || gamma > 10.0) {
134395b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
134495b296d0Smrg			   "gamma out of range (0,10.0]: %f\n",gamma);
134595b296d0Smrg		error = TRUE;
134695b296d0Smrg	    }
134795b296d0Smrg	}
134895b296d0Smrg
134995b296d0Smrg	if (!error) {
135095b296d0Smrg	    pTrident->GammaBrightnessOn = TRUE;
135195b296d0Smrg	    pTrident->gamma = gamma;
135295b296d0Smrg	    pTrident->brightness = brightness;
135395b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Gamma: %f Brightness: %i\n",
135495b296d0Smrg		       gamma,brightness);
135595b296d0Smrg	}
135695b296d0Smrg    }
135795b296d0Smrg
135895b296d0Smrg    /* The following is a temporary hack */
135995b296d0Smrg    pTrident->FPDelay = 7; /* invalid value */
136095b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_FP_DELAY,
136195b296d0Smrg			     &pTrident->FPDelay)) {
136295b296d0Smrg	if (pTrident->FPDelay < -2 || pTrident->FPDelay > 5) {
136395b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "FPDelay %i out if range "
136495b296d0Smrg		       "(-2 < FPDelay < 5)\n",pTrident->FPDelay);
136595b296d0Smrg	    pTrident->FPDelay = 7;
136695b296d0Smrg	} else
136795b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "FP Delay set to %i\n",
136895b296d0Smrg		   pTrident->FPDelay);
136995b296d0Smrg    }
137095b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_SHADOW, FALSE)) {
137195b296d0Smrg	pTrident->CyberShadow = TRUE;
137295b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Shadow enabled\n");
137395b296d0Smrg    }
137495b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_CYBER_STRETCH, FALSE)) {
137595b296d0Smrg	pTrident->CyberStretch = TRUE;
137695b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Cyber Stretch enabled\n");
137795b296d0Smrg    }
137895b296d0Smrg
137995b296d0Smrg    pTrident->MUXThreshold = 90000; /* 90MHz */
138095b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_MUX_THRESHOLD,
138195b296d0Smrg						&pTrident->MUXThreshold)) {
138295b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "MUX Threshold set to %d\n",
138395b296d0Smrg						pTrident->MUXThreshold);
138495b296d0Smrg    }
138595b296d0Smrg    pTrident->OverrideHsync = 0;
138695b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC,
138795b296d0Smrg						&pTrident->OverrideHsync)) {
138895b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n",
138995b296d0Smrg						pTrident->OverrideHsync);
139095b296d0Smrg    }
139195b296d0Smrg    pTrident->OverrideVsync = 0;
139295b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC,
139395b296d0Smrg						&pTrident->OverrideVsync)) {
139495b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n",
139595b296d0Smrg						pTrident->OverrideVsync);
139695b296d0Smrg    }
139795b296d0Smrg    pTrident->OverrideHsync = 0;
139895b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_HSYNC,
139995b296d0Smrg						&pTrident->OverrideHsync)) {
140095b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Hsync set to %d\n",
140195b296d0Smrg						pTrident->OverrideHsync);
140295b296d0Smrg    }
140395b296d0Smrg    pTrident->OverrideVsync = 0;
140495b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_VSYNC,
140595b296d0Smrg						&pTrident->OverrideVsync)) {
140695b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Vsync set to %d\n",
140795b296d0Smrg						pTrident->OverrideVsync);
140895b296d0Smrg    }
140995b296d0Smrg    pTrident->OverrideRskew = 0;
141095b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_RSKEW,
141195b296d0Smrg						&pTrident->OverrideRskew)) {
141295b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Rskew set to %d\n",
141395b296d0Smrg						pTrident->OverrideRskew);
141495b296d0Smrg    }
141595b296d0Smrg    pTrident->OverrideBskew = 0;
141695b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_XV_BSKEW,
141795b296d0Smrg						&pTrident->OverrideBskew)) {
141895b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Xv Bskew set to %d\n",
141995b296d0Smrg						pTrident->OverrideBskew);
142095b296d0Smrg    }
142195b296d0Smrg    if (xf86ReturnOptValBool(pTrident->Options, OPTION_SHADOW_FB, FALSE)) {
142295b296d0Smrg        if (!pTrident->Linear)
142395b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option SHADOW_FB"
142495b296d0Smrg		       " in non-Linear Mode\n");
142595b296d0Smrg	else {
142695b296d0Smrg	    pTrident->ShadowFB = TRUE;
142795b296d0Smrg	    pTrident->NoAccel = TRUE;
142895b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
142995b296d0Smrg		    "Using \"Shadow Framebuffer\" - acceleration disabled\n");
143095b296d0Smrg	}
143195b296d0Smrg    }
143295b296d0Smrg    pTrident->Rotate = 0;
143395b296d0Smrg    if ((s = xf86GetOptValString(pTrident->Options, OPTION_ROTATE))) {
143495b296d0Smrg        if (!pTrident->Linear)
143595b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "Ignoring Option ROTATE "
143695b296d0Smrg		       "in non-Linear Mode\n");
143795b296d0Smrg	else {
143895b296d0Smrg	    if(!xf86NameCmp(s, "CW")) {
143995b296d0Smrg	        /* accel is disabled below for shadowFB */
144095b296d0Smrg	        pTrident->ShadowFB = TRUE;
144195b296d0Smrg		pTrident->NoAccel = TRUE;
144295b296d0Smrg		pTrident->HWCursor = FALSE;
144395b296d0Smrg		pTrident->Rotate = 1;
144495b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,
144595b296d0Smrg		       "Rotating screen clockwise - acceleration disabled\n");
144695b296d0Smrg	    } else if(!xf86NameCmp(s, "CCW")) {
144795b296d0Smrg 	        pTrident->ShadowFB = TRUE;
144895b296d0Smrg		pTrident->NoAccel = TRUE;
144995b296d0Smrg		pTrident->HWCursor = FALSE;
145095b296d0Smrg		pTrident->Rotate = -1;
145195b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex, X_CONFIG,  "Rotating screen"
145295b296d0Smrg			   "counter clockwise - acceleration disabled\n");
145395b296d0Smrg	    } else {
145495b296d0Smrg	        xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "\"%s\" is not a valid"
145595b296d0Smrg			   "value for Option \"Rotate\"\n", s);
145695b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
145795b296d0Smrg			   "Valid options are \"CW\" or \"CCW\"\n");
145895b296d0Smrg	    }
145995b296d0Smrg	}
146095b296d0Smrg    }
146195b296d0Smrg
146295b296d0Smrg    pTrident->TVChipset = 0;
146395b296d0Smrg    if ((s = xf86GetOptValString(pTrident->Options, OPTION_TV_CHIPSET))) {
146495b296d0Smrg	if(!xf86NameCmp(s, "VT1621")) {
146595b296d0Smrg	    pTrident->TVChipset = 1;
146695b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Using VIA VT1621 TV chip\n");
146795b296d0Smrg	} else if (!xf86NameCmp(s, "CH7005")) {
146895b296d0Smrg	    pTrident->TVChipset = 2;
146995b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_CONFIG,"Using Chrontel CH7005 TV chip\n");
147095b296d0Smrg	} else
147195b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_ERROR,
147295b296d0Smrg		       "%s is an unknown TV chipset option\n",s);
147395b296d0Smrg    }
147495b296d0Smrg    /* Default : NTSC */
147595b296d0Smrg    pTrident->TVSignalMode=0;
147695b296d0Smrg    if (xf86GetOptValInteger(pTrident->Options, OPTION_TV_SIGNALMODE,
147795b296d0Smrg						&pTrident->TVSignalMode)) {
147895b296d0Smrg	ErrorF("TV SignalMode set to %d\n",pTrident->TVSignalMode);
147995b296d0Smrg    }
148095b296d0Smrg
148195b296d0Smrg    /* FIXME ACCELERATION */
148295b296d0Smrg    if (!UseMMIO) pTrident->NoAccel = TRUE;
148395b296d0Smrg
148495b296d0Smrg    if (pTrident->Linear) {
148595b296d0Smrg    	if (pTrident->pEnt->device->MemBase != 0) {
148695b296d0Smrg	    /*
148795b296d0Smrg	     * XXX Should check that the config file value matches one of the
148895b296d0Smrg	     * PCI base address values.
148995b296d0Smrg	     */
149095b296d0Smrg	    pTrident->FbAddress = pTrident->pEnt->device->MemBase;
149195b296d0Smrg	    from = X_CONFIG;
149295b296d0Smrg    	} else {
149395b296d0Smrg    	    if (IsPciCard)
149495b296d0Smrg	    	pTrident->FbAddress = pTrident->PciInfo->memBase[0]& 0xFFFFFFF0;
149595b296d0Smrg	    else
149695b296d0Smrg	    	pTrident->FbAddress = 0xA0000;
149795b296d0Smrg    	}
149895b296d0Smrg
149995b296d0Smrg    	xf86DrvMsg(pScrn->scrnIndex, from, "Linear framebuffer at 0x%lX\n",
150095b296d0Smrg	       (unsigned long)pTrident->FbAddress);
150195b296d0Smrg    }
150295b296d0Smrg
150395b296d0Smrg    if (UseMMIO) {
150495b296d0Smrg    	if (pTrident->pEnt->device->IOBase != 0) {
150595b296d0Smrg	    /*
150695b296d0Smrg	     * XXX Should check that the config file value matches one of the
150795b296d0Smrg	     * PCI base address values.
150895b296d0Smrg	     */
150995b296d0Smrg	    pTrident->IOAddress = pTrident->pEnt->device->IOBase;
151095b296d0Smrg	    from = X_CONFIG;
151195b296d0Smrg    	} else {
151295b296d0Smrg    	    if (IsPciCard)
151395b296d0Smrg	    	pTrident->IOAddress = pTrident->PciInfo->memBase[1]& 0xFFFFC000;
151495b296d0Smrg	    else
151595b296d0Smrg	    	/* FIXME - Multihead UNAWARE */
151695b296d0Smrg    	    	pTrident->IOAddress = 0xBF000;
151795b296d0Smrg    	}
151895b296d0Smrg
151995b296d0Smrg    	xf86DrvMsg(pScrn->scrnIndex,X_PROBED,"IO registers at 0x%lX\n",
152095b296d0Smrg		   (unsigned long)pTrident->IOAddress);
152195b296d0Smrg    }
152295b296d0Smrg
152395b296d0Smrg    /* Register the PCI-assigned resources. */
152495b296d0Smrg    if (xf86RegisterResources(pTrident->pEnt->index, NULL, ResExclusive)) {
152595b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
152695b296d0Smrg		   "xf86RegisterResources() found resource conflicts\n");
152795b296d0Smrg	return FALSE;
152895b296d0Smrg    }
152995b296d0Smrg
153095b296d0Smrg    /* Initialize VBE if possible
153195b296d0Smrg     * Don't move this past MMIO enable!!
153295b296d0Smrg     * PIO access will be blocked
153395b296d0Smrg     * when MMIO is turned on!
153495b296d0Smrg     */
153595b296d0Smrg
153695b296d0Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
153795b296d0Smrg	vbeInfoPtr pVbe;
153895b296d0Smrg
153995b296d0Smrg        xf86LoaderReqSymLists(vbeSymbols, NULL);
154095b296d0Smrg	pVbe =  VBEInit(NULL,pTrident->pEnt->index);
154195b296d0Smrg	pMon = vbeDoEDID(pVbe, NULL);
154295b296d0Smrg#ifdef VBE_INFO
154395b296d0Smrg	{
154495b296d0Smrg	    VbeInfoBlock* vbeInfoBlockPtr;
154595b296d0Smrg	    if ((vbeInfoBlockPtr = VBEGetVBEInfo(pVbe))) {
154695b296d0Smrg		pTrident->vbeModes = VBEBuildVbeModeList(pVbe,vbeInfoBlockPtr);
154795b296d0Smrg		VBEFreeVBEInfo(vbeInfoBlockPtr);
154895b296d0Smrg	    }
154995b296d0Smrg	}
155095b296d0Smrg#endif
155195b296d0Smrg	vbeFree(pVbe);
155295b296d0Smrg	if (pMon) {
155395b296d0Smrg	    if (!xf86LoadSubModule(pScrn, "ddc")) {
155495b296d0Smrg		TRIDENTFreeRec(pScrn);
155595b296d0Smrg		return FALSE;
155695b296d0Smrg	    } else {
155795b296d0Smrg		xf86LoaderReqSymLists(ddcSymbols, NULL);
155895b296d0Smrg		xf86SetDDCproperties(pScrn,xf86PrintEDID(pMon));
155995b296d0Smrg		ddcLoaded = TRUE;
156095b296d0Smrg	    }
156195b296d0Smrg	}
156295b296d0Smrg
156395b296d0Smrg    }
156495b296d0Smrg
156595b296d0Smrg    if (xf86GetOptValBool(pTrident->Options, OPTION_1400_DISPLAY, &tmp_bool)) {
156695b296d0Smrg	if (tmp_bool)
156795b296d0Smrg	    pTrident->displaySize = 1400;
156895b296d0Smrg    } else
156995b296d0Smrg	pTrident->displaySize = TRIDENTLcdDisplaySize(pMon);
157095b296d0Smrg
157195b296d0Smrg    if (IsPciCard && UseMMIO) {
157295b296d0Smrg    	if (!TRIDENTMapMem(pScrn))
157395b296d0Smrg	    return FALSE;
157495b296d0Smrg
157595b296d0Smrg    	TRIDENTEnableMMIO(pScrn);
157695b296d0Smrg    }
157795b296d0Smrg
157895b296d0Smrg    OUTB(0x3C4, RevisionID); revision = INB(0x3C5);
157995b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Revision is %d\n",revision);
158095b296d0Smrg
158195b296d0Smrg    pScrn->progClock = TRUE;
158295b296d0Smrg    pTrident->EngineOperation = 0x00;
158395b296d0Smrg    pTrident->IsCyber = FALSE;
158495b296d0Smrg    pTrident->HasSGRAM = FALSE;
158595b296d0Smrg    pTrident->NewClockCode = FALSE;
158695b296d0Smrg    pTrident->MUX = FALSE;
158795b296d0Smrg    Support24bpp = FALSE;
158895b296d0Smrg
158995b296d0Smrg    OUTB(vgaIOBase + 4, InterfaceSel);
159095b296d0Smrg
159195b296d0Smrg    switch (pTrident->Chipset) {
159295b296d0Smrg	case TVGA9000:
159395b296d0Smrg	case TVGA9000i:
159495b296d0Smrg	    pScrn->progClock = FALSE;
159595b296d0Smrg	    NoClocks = 16;
159695b296d0Smrg	    pTrident->NoMMIO = TRUE;
159795b296d0Smrg	    pTrident->NoAccel = TRUE;
159895b296d0Smrg	    pTrident->HWCursor = FALSE;
159995b296d0Smrg	    chipset = "TVGA9000/9000i";
160095b296d0Smrg	    ramtype = "Standard DRAM";
160195b296d0Smrg	    if (pTrident->UsePCIRetry)
160295b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
160395b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
160495b296d0Smrg	    pTrident->frequency = NTSC;
160595b296d0Smrg	    break;
160695b296d0Smrg	case TVGA9100B:
160795b296d0Smrg	    pScrn->progClock = FALSE;
160895b296d0Smrg	    NoClocks = 8;
160995b296d0Smrg	    pTrident->NoMMIO = TRUE;
161095b296d0Smrg	    pTrident->NoAccel = TRUE;
161195b296d0Smrg	    pTrident->HWCursor = FALSE;
161295b296d0Smrg	    chipset = "TVGA9100B";
161395b296d0Smrg	    ramtype = "Standard DRAM";
161495b296d0Smrg	    if (pTrident->UsePCIRetry)
161595b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
161695b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
161795b296d0Smrg	    pTrident->frequency = NTSC;
161895b296d0Smrg	    break;
161995b296d0Smrg	case TVGA8900B:
162095b296d0Smrg	    pScrn->progClock = FALSE;
162195b296d0Smrg	    NoClocks = 8;
162295b296d0Smrg	    pTrident->NoMMIO = TRUE;
162395b296d0Smrg	    pTrident->NoAccel = TRUE;
162495b296d0Smrg	    pTrident->HWCursor = FALSE;
162595b296d0Smrg	    chipset = "TVGA8900B";
162695b296d0Smrg	    ramtype = "Standard DRAM";
162795b296d0Smrg	    if (pTrident->UsePCIRetry)
162895b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
162995b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
163095b296d0Smrg	    pTrident->frequency = NTSC;
163195b296d0Smrg	    break;
163295b296d0Smrg	case TVGA8900C:
163395b296d0Smrg	    pScrn->progClock = FALSE;
163495b296d0Smrg	    NoClocks = 16;
163595b296d0Smrg	    pTrident->NoMMIO = TRUE;
163695b296d0Smrg	    pTrident->NoAccel = TRUE;
163795b296d0Smrg	    pTrident->HWCursor = FALSE;
163895b296d0Smrg	    chipset = "TVGA8900C";
163995b296d0Smrg	    ramtype = "Standard DRAM";
164095b296d0Smrg	    if (pTrident->UsePCIRetry)
164195b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
164295b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
164395b296d0Smrg	    pTrident->frequency = NTSC;
164495b296d0Smrg	    break;
164595b296d0Smrg	case TVGA8900D:
164695b296d0Smrg	    pScrn->progClock = FALSE;
164795b296d0Smrg	    NoClocks = 16;
164895b296d0Smrg	    pTrident->NoMMIO = TRUE;
164995b296d0Smrg	    pTrident->NoAccel = TRUE;
165095b296d0Smrg	    pTrident->HWCursor = FALSE;
165195b296d0Smrg	    chipset = "TVGA8900D";
165295b296d0Smrg	    ramtype = "Standard DRAM";
165395b296d0Smrg	    if (pTrident->UsePCIRetry)
165495b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
165595b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
165695b296d0Smrg	    pTrident->frequency = NTSC;
165795b296d0Smrg	    break;
165895b296d0Smrg	case TVGA9200CXr:
165995b296d0Smrg	    pScrn->progClock = FALSE;
166095b296d0Smrg	    NoClocks = 16;
166195b296d0Smrg	    pTrident->NoMMIO = TRUE;
166295b296d0Smrg	    pTrident->NoAccel = TRUE;
166395b296d0Smrg	    pTrident->HWCursor = FALSE;
166495b296d0Smrg	    chipset = "TVGA9200CXr";
166595b296d0Smrg	    ramtype = "Standard DRAM";
166695b296d0Smrg	    if (pTrident->UsePCIRetry)
166795b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
166895b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
166995b296d0Smrg	    pTrident->frequency = NTSC;
167095b296d0Smrg	    break;
167195b296d0Smrg	case TGUI9400CXi:
167295b296d0Smrg	    pScrn->progClock = FALSE;
167395b296d0Smrg	    NoClocks = 16;
167495b296d0Smrg	    pTrident->NoMMIO = TRUE;
167595b296d0Smrg	    pTrident->NoAccel = TRUE;
167695b296d0Smrg	    pTrident->HWCursor = FALSE;
167795b296d0Smrg	    chipset = "TVGA9200CXr";
167895b296d0Smrg	    ramtype = "Standard DRAM";
167995b296d0Smrg	    if (pTrident->UsePCIRetry)
168095b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
168195b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
168295b296d0Smrg	    pTrident->frequency = NTSC;
168395b296d0Smrg	    break;
168495b296d0Smrg	case TGUI9440AGi:
168595b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
168695b296d0Smrg	    pTrident->HWCursor = FALSE;
168795b296d0Smrg	    chipset = "TGUI9440AGi";
168895b296d0Smrg	    ramtype = "Standard DRAM";
168995b296d0Smrg	    if (pTrident->UsePCIRetry)
169095b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
169195b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
169295b296d0Smrg	    pTrident->frequency = NTSC;
169395b296d0Smrg	    break;
169495b296d0Smrg	case CYBER9320:
169595b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
169695b296d0Smrg	    chipset = "Cyber9320";
169795b296d0Smrg	    ramtype = "Standard DRAM";
169895b296d0Smrg	    if (pTrident->UsePCIRetry)
169995b296d0Smrg	    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
170095b296d0Smrg	    pTrident->UsePCIRetry = FALSE; /* Not Supported */
170195b296d0Smrg	    break;
170295b296d0Smrg	/* Trident didn't update the PCI ID's and so we have to detemine
170395b296d0Smrg	 * which chips are right ! Then override pTrident->Chipset to
170495b296d0Smrg	 * correct values */
170595b296d0Smrg	case TGUI9660:
170695b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
170795b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
170895b296d0Smrg		ramtype = "EDO Ram";
170995b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C)
171095b296d0Smrg		ramtype = "Standard DRAM";
171195b296d0Smrg	    switch (revision) {
171295b296d0Smrg		case 0x00:
171395b296d0Smrg		    chipset = "TGUI9660";
171495b296d0Smrg		    pTrident->Chipset = TGUI9660;
171595b296d0Smrg		    if (pTrident->UsePCIRetry)
171695b296d0Smrg		    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
171795b296d0Smrg		    pTrident->UsePCIRetry = FALSE; /* Not Supported */
171895b296d0Smrg		    break;
171995b296d0Smrg		case 0x01:
172095b296d0Smrg		    chipset = "TGUI9680";
172195b296d0Smrg		    pTrident->Chipset = TGUI9680;
172295b296d0Smrg		    if (pTrident->UsePCIRetry)
172395b296d0Smrg		    	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "PCI retry not supported, disabling\n");
172495b296d0Smrg		    pTrident->UsePCIRetry = FALSE; /* Not Supported */
172595b296d0Smrg		    break;
172695b296d0Smrg		case 0x10:
172795b296d0Smrg		    chipset = "ProVidia 9682";
172895b296d0Smrg		    Support24bpp = TRUE;
172995b296d0Smrg		    pTrident->Chipset = PROVIDIA9682;
173095b296d0Smrg		    break;
173195b296d0Smrg		case 0x21:
173295b296d0Smrg		    chipset = "ProVidia 9685";
173395b296d0Smrg		    Support24bpp = TRUE;
173495b296d0Smrg		    pTrident->NewClockCode = TRUE;
173595b296d0Smrg		    pTrident->Chipset = PROVIDIA9685;
173695b296d0Smrg		    break;
173795b296d0Smrg		case 0x22:
173895b296d0Smrg		case 0x23:
173995b296d0Smrg		    chipset = "Cyber 9397";
174095b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
174195b296d0Smrg			ramtype = "EDO Ram";
174295b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
174395b296d0Smrg			ramtype = "SDRAM";
174495b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
174595b296d0Smrg			pTrident->HasSGRAM = TRUE;
174695b296d0Smrg			ramtype = "SGRAM";
174795b296d0Smrg	    	    }
174895b296d0Smrg		    pTrident->NewClockCode = TRUE;
174995b296d0Smrg		    pTrident->Chipset = CYBER9397;
175095b296d0Smrg		    pTrident->IsCyber = TRUE;
175195b296d0Smrg		    break;
175295b296d0Smrg		case 0x2a:
175395b296d0Smrg		    chipset = "Cyber 9397/DVD";
175495b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
175595b296d0Smrg			ramtype = "EDO Ram";
175695b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
175795b296d0Smrg			ramtype = "SDRAM";
175895b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
175995b296d0Smrg			pTrident->HasSGRAM = TRUE;
176095b296d0Smrg			ramtype = "SGRAM";
176195b296d0Smrg	    	    }
176295b296d0Smrg		    pTrident->NewClockCode = TRUE;
176395b296d0Smrg		    pTrident->Chipset = CYBER9397DVD;
176495b296d0Smrg		    pTrident->IsCyber = TRUE;
176595b296d0Smrg		    break;
176695b296d0Smrg		case 0x30:
176795b296d0Smrg		case 0x33:
176895b296d0Smrg		case 0x34:
176995b296d0Smrg		case 0x35:
177095b296d0Smrg		case 0xB3:
177195b296d0Smrg		    chipset = "Cyber 9385";
177295b296d0Smrg		    pTrident->NewClockCode = TRUE;
177395b296d0Smrg		    pTrident->Chipset = CYBER9385;
177495b296d0Smrg		    pTrident->IsCyber = TRUE;
177595b296d0Smrg		    break;
177695b296d0Smrg		case 0x38:
177795b296d0Smrg		case 0x3A:
177895b296d0Smrg		    chipset = "Cyber 9385-1";
177995b296d0Smrg		    pTrident->NewClockCode = TRUE;
178095b296d0Smrg		    pTrident->Chipset = CYBER9385;
178195b296d0Smrg		    pTrident->IsCyber = TRUE;
178295b296d0Smrg		    break;
178395b296d0Smrg		case 0x40:
178495b296d0Smrg		case 0x41:
178595b296d0Smrg		case 0x42:
178695b296d0Smrg		case 0x43:
178795b296d0Smrg		    chipset = "Cyber 9382";
178895b296d0Smrg		    pTrident->NewClockCode = TRUE;
178995b296d0Smrg		    pTrident->Chipset = CYBER9382;
179095b296d0Smrg		    pTrident->IsCyber = TRUE;
179195b296d0Smrg		    break;
179295b296d0Smrg		case 0x4A:
179395b296d0Smrg		    chipset = "Cyber 9388";
179495b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
179595b296d0Smrg			ramtype = "EDO Ram";
179695b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
179795b296d0Smrg			ramtype = "SDRAM";
179895b296d0Smrg    	    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
179995b296d0Smrg			pTrident->HasSGRAM = TRUE;
180095b296d0Smrg			ramtype = "SGRAM";
180195b296d0Smrg	    	    }
180295b296d0Smrg		    pTrident->NewClockCode = TRUE;
180395b296d0Smrg		    pTrident->Chipset = CYBER9388;
180495b296d0Smrg		    pTrident->IsCyber = TRUE;
180595b296d0Smrg		    break;
180695b296d0Smrg		default:
180795b296d0Smrg		    chipset = "Unknown";
180895b296d0Smrg		    pTrident->Chipset = TGUI9660;
180995b296d0Smrg		    break;
181095b296d0Smrg	    }
181195b296d0Smrg	    break;
181295b296d0Smrg	case CYBER9388:
181395b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
181495b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
181595b296d0Smrg		ramtype = "EDO Ram";
181695b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
181795b296d0Smrg		ramtype = "SDRAM";
181895b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
181995b296d0Smrg		pTrident->HasSGRAM = TRUE;
182095b296d0Smrg		ramtype = "SGRAM";
182195b296d0Smrg	    }
182295b296d0Smrg	    pTrident->IsCyber = TRUE;
182395b296d0Smrg	    Support24bpp = TRUE;
182495b296d0Smrg	    chipset = "Cyber 9388";
182595b296d0Smrg	    pTrident->NewClockCode = TRUE;
182695b296d0Smrg	    break;
182795b296d0Smrg	case CYBER9397:
182895b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
182995b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
183095b296d0Smrg		ramtype = "EDO Ram";
183195b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
183295b296d0Smrg		ramtype = "SDRAM";
183395b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
183495b296d0Smrg		pTrident->HasSGRAM = TRUE;
183595b296d0Smrg		ramtype = "SGRAM";
183695b296d0Smrg	    }
183795b296d0Smrg	    pTrident->IsCyber = TRUE;
183895b296d0Smrg	    Support24bpp = TRUE;
183995b296d0Smrg	    chipset = "Cyber 9397";
184095b296d0Smrg	    pTrident->NewClockCode = TRUE;
184195b296d0Smrg	    break;
184295b296d0Smrg	case CYBER9397DVD:
184395b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
184495b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
184595b296d0Smrg		ramtype = "EDO Ram";
184695b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
184795b296d0Smrg		ramtype = "SDRAM";
184895b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
184995b296d0Smrg		pTrident->HasSGRAM = TRUE;
185095b296d0Smrg		ramtype = "SGRAM";
185195b296d0Smrg	    }
185295b296d0Smrg	    pTrident->IsCyber = TRUE;
185395b296d0Smrg	    Support24bpp = TRUE;
185495b296d0Smrg	    chipset = "Cyber 9397/DVD";
185595b296d0Smrg	    pTrident->NewClockCode = TRUE;
185695b296d0Smrg	    break;
185795b296d0Smrg	case CYBER9520:
185895b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
185995b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
186095b296d0Smrg		ramtype = "EDO Ram";
186195b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
186295b296d0Smrg		ramtype = "SDRAM";
186395b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
186495b296d0Smrg		pTrident->HasSGRAM = TRUE;
186595b296d0Smrg		ramtype = "SGRAM";
186695b296d0Smrg	    }
186795b296d0Smrg	    pTrident->IsCyber = TRUE;
186895b296d0Smrg	    Support24bpp = TRUE;
186995b296d0Smrg	    chipset = "Cyber 9520";
187095b296d0Smrg	    pTrident->NewClockCode = TRUE;
187195b296d0Smrg	    break;
187295b296d0Smrg	case CYBER9525DVD:
187395b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
187495b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
187595b296d0Smrg		ramtype = "EDO Ram";
187695b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
187795b296d0Smrg		ramtype = "SDRAM";
187895b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
187995b296d0Smrg		pTrident->HasSGRAM = TRUE;
188095b296d0Smrg		ramtype = "SGRAM";
188195b296d0Smrg	    }
188295b296d0Smrg	    pTrident->IsCyber = TRUE;
188395b296d0Smrg	    Support24bpp = TRUE;
188495b296d0Smrg	    chipset = "Cyber 9525/DVD";
188595b296d0Smrg	    pTrident->NewClockCode = TRUE;
188695b296d0Smrg	    break;
188795b296d0Smrg	case CYBERBLADEE4:
188895b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
188995b296d0Smrg	    ramtype = "SDRAM";
189095b296d0Smrg	    pTrident->IsCyber = TRUE;
189195b296d0Smrg	    Support24bpp = TRUE;
189295b296d0Smrg	    chipset = "CyberBlade e4/128";
189395b296d0Smrg	    pTrident->NewClockCode = TRUE;
189495b296d0Smrg	    break;
189595b296d0Smrg	case IMAGE975:
189695b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
189795b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
189895b296d0Smrg		ramtype = "EDO Ram";
189995b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
190095b296d0Smrg		ramtype = "SDRAM";
190195b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
190295b296d0Smrg		pTrident->HasSGRAM = TRUE;
190395b296d0Smrg		ramtype = "SGRAM";
190495b296d0Smrg	    }
190595b296d0Smrg	    Support24bpp = TRUE;
190695b296d0Smrg	    chipset = "3DImage975";
190795b296d0Smrg	    pTrident->NewClockCode = TRUE;
190895b296d0Smrg	    break;
190995b296d0Smrg	case IMAGE985:
191095b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
191195b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x04)
191295b296d0Smrg		ramtype = "EDO Ram";
191395b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
191495b296d0Smrg		ramtype = "SDRAM";
191595b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
191695b296d0Smrg		pTrident->HasSGRAM = TRUE;
191795b296d0Smrg		ramtype = "SGRAM";
191895b296d0Smrg	    }
191995b296d0Smrg	    Support24bpp = TRUE;
192095b296d0Smrg	    chipset = "3DImage985";
192195b296d0Smrg	    pTrident->NewClockCode = TRUE;
192295b296d0Smrg	    break;
192395b296d0Smrg	case BLADE3D:
192495b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
192595b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x08)
192695b296d0Smrg		ramtype = "SDRAM";
192795b296d0Smrg    	    if ((INB(vgaIOBase + 5) & 0x0C) == 0x0C) {
192895b296d0Smrg		pTrident->HasSGRAM = TRUE;
192995b296d0Smrg		ramtype = "SGRAM";
193095b296d0Smrg	    }
193195b296d0Smrg	    Support24bpp = TRUE;
193295b296d0Smrg	    chipset = "Blade3D";
193395b296d0Smrg	    pTrident->NewClockCode = TRUE;
193495b296d0Smrg	    pTrident->frequency = NTSC;
193595b296d0Smrg	    pTrident->UsePCIRetry = TRUE; /* To avoid lockups */
193695b296d0Smrg	    break;
193795b296d0Smrg	case CYBERBLADEI7:
193895b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
193995b296d0Smrg	    ramtype = "SDRAM";
194095b296d0Smrg	    /* pTrident->IsCyber = TRUE; VIA MVP4 integrated Desktop version */
194195b296d0Smrg	    Support24bpp = TRUE;
194295b296d0Smrg	    chipset = "CyberBlade/i7/VIA MVP4";
194395b296d0Smrg	    pTrident->NewClockCode = TRUE;
194495b296d0Smrg	    pTrident->frequency = NTSC;
194595b296d0Smrg	    break;
194695b296d0Smrg	case CYBERBLADEI7D:
194795b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
194895b296d0Smrg	    ramtype = "SDRAM";
194995b296d0Smrg	    pTrident->IsCyber = TRUE;
195095b296d0Smrg	    Support24bpp = TRUE;
195195b296d0Smrg	    chipset = "CyberBlade/DSTN/i7";
195295b296d0Smrg	    pTrident->NewClockCode = TRUE;
195395b296d0Smrg	    pTrident->frequency = NTSC;
195495b296d0Smrg	    break;
195595b296d0Smrg	case CYBERBLADEI1:
195695b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
195795b296d0Smrg	    ramtype = "SDRAM";
195895b296d0Smrg	    pTrident->IsCyber = TRUE;
195995b296d0Smrg	    Support24bpp = TRUE;
196095b296d0Smrg	    chipset = "CyberBlade/i1";
196195b296d0Smrg	    pTrident->NewClockCode = TRUE;
196295b296d0Smrg	    pTrident->frequency = NTSC;
196395b296d0Smrg	    break;
196495b296d0Smrg	case CYBERBLADEI1D:
196595b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
196695b296d0Smrg	    ramtype = "SDRAM";
196795b296d0Smrg	    pTrident->IsCyber = TRUE;
196895b296d0Smrg	    Support24bpp = TRUE;
196995b296d0Smrg	    chipset = "CyberBlade/DSTN/i1";
197095b296d0Smrg	    pTrident->NewClockCode = TRUE;
197195b296d0Smrg	    pTrident->frequency = NTSC;
197295b296d0Smrg	    break;
197395b296d0Smrg	case CYBERBLADEAI1:
197495b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
197595b296d0Smrg	    ramtype = "SDRAM";
197695b296d0Smrg	    pTrident->IsCyber = TRUE;
197795b296d0Smrg	    Support24bpp = TRUE;
197895b296d0Smrg	    chipset = "CyberBlade/Ai1";
197995b296d0Smrg	    pTrident->NewClockCode = TRUE;
198095b296d0Smrg	    pTrident->frequency = NTSC;
198195b296d0Smrg	    break;
198295b296d0Smrg	case CYBERBLADEAI1D:
198395b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
198495b296d0Smrg	    ramtype = "SDRAM";
198595b296d0Smrg	    pTrident->IsCyber = TRUE;
198695b296d0Smrg	    Support24bpp = TRUE;
198795b296d0Smrg	    chipset = "CyberBlade/DSTN/Ai1";
198895b296d0Smrg	    pTrident->NewClockCode = TRUE;
198995b296d0Smrg	    pTrident->frequency = NTSC;
199095b296d0Smrg	    break;
199195b296d0Smrg	case BLADEXP: /* 0x9910 */
199295b296d0Smrg	    pTrident->ddc1Read = Tridentddc1Read;
199395b296d0Smrg	    ramtype = "SGRAM";
199495b296d0Smrg	    pTrident->HasSGRAM = TRUE;
199595b296d0Smrg	    Support24bpp = TRUE;
199695b296d0Smrg	    pTrident->NewClockCode = TRUE;
199795b296d0Smrg	    pTrident->frequency = NTSC;
199895b296d0Smrg	    OUTB(0x3C4, 0x5D);
199995b296d0Smrg	    if (pTrident->PciInfo->subsysVendor != 0x1023) {
200095b296d0Smrg	    	chipset = "CyberBladeXP";
200195b296d0Smrg	    	pTrident->IsCyber = TRUE;
200295b296d0Smrg	    } else
200395b296d0Smrg	    if (!(INB(0x3C5) & 0x01)) {
200495b296d0Smrg	    	chipset = "BladeXP";
200595b296d0Smrg	    } else {
200695b296d0Smrg		CARD8 mem1, mem2;
200795b296d0Smrg		OUTB(vgaIOBase + 0x04, SPR);
200895b296d0Smrg		mem1 = INB(vgaIOBase + 5);
200995b296d0Smrg		OUTB(vgaIOBase + 0x04, 0xC1);
201095b296d0Smrg		mem2 = INB(vgaIOBase + 5);
201195b296d0Smrg		if ((mem1 & 0x0e) && (mem2 == 0x11)) {
201295b296d0Smrg	    	    chipset = "BladeT64";
201395b296d0Smrg		} else {
201495b296d0Smrg	    	    chipset = "BladeT16";
201595b296d0Smrg		}
201695b296d0Smrg	    }
201795b296d0Smrg	    break;
201895b296d0Smrg	case CYBERBLADEXPAI1:
201995b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
202095b296d0Smrg	    ramtype = "SGRAM";
202195b296d0Smrg            pTrident->HasSGRAM = TRUE;
202295b296d0Smrg	    pTrident->IsCyber = TRUE;
202395b296d0Smrg	    pTrident->shadowNew = TRUE;
202495b296d0Smrg	    Support24bpp = TRUE;
202595b296d0Smrg	    chipset = "CyberBladeXPAi1";
202695b296d0Smrg	    pTrident->NewClockCode = TRUE;
202795b296d0Smrg	    pTrident->frequency = NTSC;
202895b296d0Smrg	    break;
202995b296d0Smrg	case CYBERBLADEXP4:
203095b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
203195b296d0Smrg	    ramtype = "SGRAM";
203295b296d0Smrg            pTrident->HasSGRAM = TRUE;
203395b296d0Smrg	    pTrident->IsCyber = TRUE;
203495b296d0Smrg	    pTrident->shadowNew = TRUE;
203595b296d0Smrg	    Support24bpp = TRUE;
203695b296d0Smrg	    chipset = "CyberBladeXP4";
203795b296d0Smrg	    pTrident->NewClockCode = TRUE;
203895b296d0Smrg	    pTrident->frequency = NTSC;
203995b296d0Smrg	    break;
204095b296d0Smrg	case XP5:
204195b296d0Smrg    	    pTrident->ddc1Read = Tridentddc1Read;
204295b296d0Smrg	    ramtype = "SGRAM";
204395b296d0Smrg            pTrident->HasSGRAM = TRUE;
204495b296d0Smrg	    pTrident->IsCyber = TRUE;
204595b296d0Smrg	    pTrident->shadowNew = TRUE;
204695b296d0Smrg	    Support24bpp = TRUE;
204795b296d0Smrg	    chipset = "XP5";
204895b296d0Smrg	    pTrident->NewClockCode = TRUE;
204995b296d0Smrg	    pTrident->frequency = NTSC;
205095b296d0Smrg	    break;
205195b296d0Smrg    }
205295b296d0Smrg
205395b296d0Smrg    if (!pScrn->progClock) {
205495b296d0Smrg	pScrn->numClocks = NoClocks;
205595b296d0Smrg	xf86GetClocks(pScrn, NoClocks, TRIDENTClockSelect,
205695b296d0Smrg			  vgaHWProtectWeak(),
205795b296d0Smrg			  vgaHWBlankScreenWeak(),
205895b296d0Smrg			  vgaIOBase + 0x0A, 0x08, 1, 28322);
205995b296d0Smrg	from = X_PROBED;
206095b296d0Smrg	xf86ShowClocks(pScrn, from);
206195b296d0Smrg    }
206295b296d0Smrg
206395b296d0Smrg    if (!chipset) {
206495b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No support for \"%s\"\n",
206595b296d0Smrg			pScrn->chipset);
206695b296d0Smrg	if (IsPciCard && UseMMIO) {
206795b296d0Smrg    	    TRIDENTDisableMMIO(pScrn);
206895b296d0Smrg 	    TRIDENTUnmapMem(pScrn);
206995b296d0Smrg	}
207095b296d0Smrg	return FALSE;
207195b296d0Smrg    }
207295b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Found %s chip\n", chipset);
207395b296d0Smrg    if (ramtype)
207495b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "RAM type is %s\n", ramtype);
207595b296d0Smrg
207695b296d0Smrg    if (pScrn->bitsPerPixel == 24 && !Support24bpp) {
207795b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "No support for 24bpp on this chipset, use -pixmap32.\n");
207895b296d0Smrg	if (IsPciCard && UseMMIO) {
207995b296d0Smrg    	    TRIDENTDisableMMIO(pScrn);
208095b296d0Smrg 	    TRIDENTUnmapMem(pScrn);
208195b296d0Smrg	}
208295b296d0Smrg	return FALSE;
208395b296d0Smrg    }
208495b296d0Smrg
208595b296d0Smrg    /* HW bpp matches reported bpp */
208695b296d0Smrg    pTrident->HwBpp = pScrn->bitsPerPixel;
208795b296d0Smrg
208895b296d0Smrg    /* Due to bugs in the chip, turn it off */
208995b296d0Smrg    if (pTrident->Chipset >= CYBERBLADEI7 && pTrident->Chipset <= CYBERBLADEAI1D)
209095b296d0Smrg	pTrident->HWCursor = FALSE;
209195b296d0Smrg
209295b296d0Smrg    from = X_PROBED;
209395b296d0Smrg    if (pTrident->pEnt->device->videoRam != 0) {
209495b296d0Smrg	pScrn->videoRam = pTrident->pEnt->device->videoRam;
209595b296d0Smrg	from = X_CONFIG;
209695b296d0Smrg    } else {
209795b296d0Smrg      if (pTrident->Chipset == XP5) {
209895b296d0Smrg	OUTB(vgaIOBase + 4, 0x60);
209995b296d0Smrg	videoram = INB(vgaIOBase + 5);
210095b296d0Smrg	switch (videoram & 0x7) {
210195b296d0Smrg 	case 0x00:
210295b296d0Smrg	    pScrn->videoRam = 65536 /* 131072 */;
210395b296d0Smrg	    break;
210495b296d0Smrg	case 0x01:
210595b296d0Smrg	    pScrn->videoRam = 65536;
210695b296d0Smrg	    break;
210795b296d0Smrg	case 0x02:
210895b296d0Smrg	    pScrn->videoRam = 32768;
210995b296d0Smrg	    break;
211095b296d0Smrg	case 0x03:
211195b296d0Smrg	    pScrn->videoRam = 16384;
211295b296d0Smrg	    break;
211395b296d0Smrg	case 0x04:
211495b296d0Smrg	    pScrn->videoRam = 8192;
211595b296d0Smrg	    break;
211695b296d0Smrg	}
211795b296d0Smrg      } else
211895b296d0Smrg      if (pTrident->Chipset == CYBER9525DVD) {
211995b296d0Smrg	pScrn->videoRam = 2560;
212095b296d0Smrg      } else
212195b296d0Smrg      {
212295b296d0Smrg	OUTB(vgaIOBase + 4, SPR);
212395b296d0Smrg	videoram = INB(vgaIOBase + 5);
212495b296d0Smrg	if (pTrident->Chipset < TGUI9440AGi)
212595b296d0Smrg	    videorammask = 0x07;
212695b296d0Smrg	else
212795b296d0Smrg	    videorammask = 0x0F;
212895b296d0Smrg	switch (videoram & videorammask) {
212995b296d0Smrg  	case 0x01:
213095b296d0Smrg  	    pScrn->videoRam = 512;
213195b296d0Smrg  	    break;
213295b296d0Smrg 	case 0x02: /* XP */
213395b296d0Smrg 	    pScrn->videoRam = 6144;
213495b296d0Smrg 	    break;
213595b296d0Smrg  	case 0x03:
213695b296d0Smrg  	    pScrn->videoRam = 1024;
213795b296d0Smrg  	    break;
213895b296d0Smrg	case 0x04:
213995b296d0Smrg	    pScrn->videoRam = 8192;
214095b296d0Smrg	    break;
214195b296d0Smrg 	case 0x06: /* XP */
214295b296d0Smrg 	    pScrn->videoRam = 10240;
214395b296d0Smrg 	    break;
214495b296d0Smrg  	case 0x07:
214595b296d0Smrg  	    pScrn->videoRam = 2048;
214695b296d0Smrg  	    break;
214795b296d0Smrg 	case 0x08: /* XP */
214895b296d0Smrg 	    pScrn->videoRam = 12288;
214995b296d0Smrg 	    break;
215095b296d0Smrg 	case 0x0A: /* XP */
215195b296d0Smrg 	    pScrn->videoRam = 14336;
215295b296d0Smrg 	    break;
215395b296d0Smrg 	case 0x0C: /* XP */
215495b296d0Smrg 	    pScrn->videoRam = 16384;
215595b296d0Smrg 	    break;
215695b296d0Smrg 	case 0x0E: /* XP */
215795b296d0Smrg 	    OUTB(vgaIOBase + 4, 0xC1);
215895b296d0Smrg 	    switch (INB(vgaIOBase + 5) & 0x11) {
215995b296d0Smrg 		case 0x00:
216095b296d0Smrg 		    pScrn->videoRam = 20480;
216195b296d0Smrg 		    break;
216295b296d0Smrg 		case 0x01:
216395b296d0Smrg 		    pScrn->videoRam = 24576;
216495b296d0Smrg 		    break;
216595b296d0Smrg 		case 0x10:
216695b296d0Smrg 		    pScrn->videoRam = 28672;
216795b296d0Smrg 		    break;
216895b296d0Smrg 		case 0x11:
216995b296d0Smrg 		    pScrn->videoRam = 32768;
217095b296d0Smrg 		    break;
217195b296d0Smrg 	    }
217295b296d0Smrg 	    break;
217395b296d0Smrg 	case 0x0F:
217495b296d0Smrg  	    pScrn->videoRam = 4096;
217595b296d0Smrg  	    break;
217695b296d0Smrg	default:
217795b296d0Smrg	    pScrn->videoRam = 1024;
217895b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex, from,
217995b296d0Smrg			"Unable to determine VideoRam, defaulting to 1MB\n");
218095b296d0Smrg	    break;
218195b296d0Smrg	}
218295b296d0Smrg      }
218395b296d0Smrg    }
218495b296d0Smrg
218595b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %s cursor\n",
218695b296d0Smrg		pTrident->HWCursor ? "HW" : "SW");
218795b296d0Smrg
218895b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "VideoRAM: %d kByte\n",
218995b296d0Smrg               pScrn->videoRam);
219095b296d0Smrg
219195b296d0Smrg    if (pTrident->IsCyber) {
219295b296d0Smrg	unsigned char mod, dsp, dsp1;
219395b296d0Smrg
219495b296d0Smrg	pTrident->lcdMode = 0xff;
219595b296d0Smrg
219695b296d0Smrg	OUTB(0x3CE,0x42);
219795b296d0Smrg	dsp = INB(0x3CF);
219895b296d0Smrg	OUTB(0x3CE,0x43);
219995b296d0Smrg	dsp1 = INB(0x3CF);
220095b296d0Smrg	OUTB(0x3CE,0x52);
220195b296d0Smrg	mod = INB(0x3CF);
220295b296d0Smrg	/*
220395b296d0Smrg	 * Only allow display size override if 1280x1024 is detected
220495b296d0Smrg	 * Currently 1400x1050 is supported - which is detected as
220595b296d0Smrg	 * 1280x1024
220695b296d0Smrg	 */
220795b296d0Smrg	if (pTrident->displaySize) {
220895b296d0Smrg	    if (((mod >> 4) & 3) == 0) {
220995b296d0Smrg		for (i = 0; LCD[i].mode != 0xff; i++) {
221095b296d0Smrg		    if (pTrident->displaySize == LCD[i].display_x)
221195b296d0Smrg			pTrident->lcdMode = LCD[i].mode;
221295b296d0Smrg		}
221395b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex,
221495b296d0Smrg			   X_INFO,"%s Panel %ix%i found\n",
221595b296d0Smrg			   (dsp & 0x80) ? "TFT" :
221695b296d0Smrg			   ((dsp1 & 0x20) ? "DSTN" : "STN"),
221795b296d0Smrg			   LCD[i].display_x,LCD[i].display_y);
221895b296d0Smrg	    } else {
221995b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex,X_WARNING,
222095b296d0Smrg			   "Display size override only for 1280x1024\n");
222195b296d0Smrg		pTrident->displaySize = 0;
222295b296d0Smrg	    }
222395b296d0Smrg	}
222495b296d0Smrg
222595b296d0Smrg	if (!pTrident->displaySize) {
222695b296d0Smrg	    for (i = 0; LCD[i].mode != 0xff; i++) {
222795b296d0Smrg		if (LCD[i].mode == ((mod >> 4) & 3)) {
222895b296d0Smrg		    pTrident->lcdMode = i;
222995b296d0Smrg		    xf86DrvMsg(pScrn->scrnIndex,
223095b296d0Smrg			       X_PROBED,"%s Panel %ix%i found\n",
223195b296d0Smrg			       (dsp & 0x80) ? "TFT" :
223295b296d0Smrg			       ((dsp1 & 0x20) ? "DSTN" : "STN"),
223395b296d0Smrg			       LCD[i].display_x,LCD[i].display_y);
223495b296d0Smrg		}
223595b296d0Smrg	    }
223695b296d0Smrg	}
223795b296d0Smrg	if (pTrident->dspOverride) {
223895b296d0Smrg	    if (pTrident->dspOverride & LCD_ACTIVE)
223995b296d0Smrg		pTrident->lcdActive = TRUE;
224095b296d0Smrg	    else
224195b296d0Smrg		pTrident->lcdActive = FALSE;
224295b296d0Smrg	} else {
224395b296d0Smrg	    OUTB(0x3CE, FPConfig);
224495b296d0Smrg	    pTrident->lcdActive = (INB(0x3CF) & 0x10);
224595b296d0Smrg	}
224695b296d0Smrg    }
224795b296d0Smrg
224895b296d0Smrg    pTrident->MCLK = 0;
224995b296d0Smrg    mclk = CalculateMCLK(pScrn);
225095b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "Memory Clock is %3.2f MHz\n", mclk);
225195b296d0Smrg    if (xf86GetOptValFreq(pTrident->Options, OPTION_SETMCLK, OPTUNITS_MHZ,
225295b296d0Smrg				&real)) {
225395b296d0Smrg	pTrident->MCLK = (int)(real * 1000.0);
225495b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Setting new Memory Clock to %3.2f MHz\n",
225595b296d0Smrg						(float)(pTrident->MCLK / 1000));
225695b296d0Smrg    }
225795b296d0Smrg
225895b296d0Smrg    /* Set the min pixel clock */
225995b296d0Smrg    pTrident->MinClock = 12000;	/* XXX Guess, need to check this */
226095b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, X_DEFAULT, "Min pixel clock is %d MHz\n",
226195b296d0Smrg	       pTrident->MinClock / 1000);
226295b296d0Smrg
226395b296d0Smrg    /*
226495b296d0Smrg     * If the user has specified ramdac speed in the XF86Config
226595b296d0Smrg     * file, we respect that setting.
226695b296d0Smrg     */
226795b296d0Smrg    if (pTrident->pEnt->device->dacSpeeds[0]) {
226895b296d0Smrg	int speed = 0;
226995b296d0Smrg
227095b296d0Smrg	switch (pScrn->bitsPerPixel) {
227195b296d0Smrg	case 8:
227295b296d0Smrg	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP8];
227395b296d0Smrg	   break;
227495b296d0Smrg	case 16:
227595b296d0Smrg	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP16];
227695b296d0Smrg	   break;
227795b296d0Smrg	case 24:
227895b296d0Smrg	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP24];
227995b296d0Smrg	   break;
228095b296d0Smrg	case 32:
228195b296d0Smrg	   speed = pTrident->pEnt->device->dacSpeeds[DAC_BPP32];
228295b296d0Smrg	   break;
228395b296d0Smrg	}
228495b296d0Smrg	if (speed == 0)
228595b296d0Smrg	    pTrident->MaxClock = pTrident->pEnt->device->dacSpeeds[0];
228695b296d0Smrg	else
228795b296d0Smrg	    pTrident->MaxClock = speed;
228895b296d0Smrg	from = X_CONFIG;
228995b296d0Smrg    } else {
229095b296d0Smrg	switch (pScrn->bitsPerPixel) {
229195b296d0Smrg	    case 16:
229295b296d0Smrg		pTrident->MaxClock = ClockLimit16bpp[pTrident->Chipset];
229395b296d0Smrg		break;
229495b296d0Smrg	    case 24:
229595b296d0Smrg		pTrident->MaxClock = ClockLimit24bpp[pTrident->Chipset];
229695b296d0Smrg		break;
229795b296d0Smrg	    case 32:
229895b296d0Smrg		pTrident->MaxClock = ClockLimit32bpp[pTrident->Chipset];
229995b296d0Smrg		break;
230095b296d0Smrg	    default:
230195b296d0Smrg		pTrident->MaxClock = ClockLimit[pTrident->Chipset];
230295b296d0Smrg		break;
230395b296d0Smrg	}
230495b296d0Smrg    }
230595b296d0Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Max pixel clock is %d MHz\n",
230695b296d0Smrg	       pTrident->MaxClock / 1000);
230795b296d0Smrg
230895b296d0Smrg    /*
230995b296d0Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
231095b296d0Smrg     * and what sort of modes they can be used for.
231195b296d0Smrg     */
231295b296d0Smrg    clockRanges = xnfcalloc(sizeof(ClockRange), 1);
231395b296d0Smrg    clockRanges->next = NULL;
231495b296d0Smrg    if (!pScrn->progClock) {
231595b296d0Smrg	if (pScrn->videoRam < 1024)
231695b296d0Smrg    	    clockRanges->ClockMulFactor = 2;
231795b296d0Smrg	if (pScrn->bitsPerPixel == 16)
231895b296d0Smrg    	    clockRanges->ClockMulFactor = 2;
231995b296d0Smrg    }
232095b296d0Smrg    clockRanges->minClock = pTrident->MinClock;
232195b296d0Smrg    clockRanges->maxClock = pTrident->MaxClock;
232295b296d0Smrg    clockRanges->clockIndex = -1;		/* programmable */
232395b296d0Smrg    clockRanges->interlaceAllowed = TRUE;
232495b296d0Smrg    clockRanges->doubleScanAllowed = FALSE;	/* XXX check this */
232595b296d0Smrg
232695b296d0Smrg    /*
232795b296d0Smrg     * xf86ValidateModes will check that the mode HTotal and VTotal values
232895b296d0Smrg     * don't exceed the chipset's limit if pScrn->maxHValue and
232995b296d0Smrg     * pScrn->maxVValue are set.  Since our TRIDENTValidMode() already takes
233095b296d0Smrg     * care of this, we don't worry about setting them here.
233195b296d0Smrg     */
233295b296d0Smrg
233395b296d0Smrg    if (pScrn->bitsPerPixel == 24) {
233495b296d0Smrg    	    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
233595b296d0Smrg		"Disabling Engine due to 24bpp.\n");
233695b296d0Smrg	    pTrident->NoAccel = TRUE;
233795b296d0Smrg    }
233895b296d0Smrg
233995b296d0Smrg    /* Select valid modes from those available */
234095b296d0Smrg    if (pTrident->NoAccel || Is3Dchip) {
234195b296d0Smrg	/*
234295b296d0Smrg	 * XXX Assuming min pitch 256, max 4096
234395b296d0Smrg	 * XXX Assuming min height 128, max 4096
234495b296d0Smrg	 */
234595b296d0Smrg	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
234695b296d0Smrg			      pScrn->display->modes, clockRanges,
234795b296d0Smrg			      NULL, 256, 4096,
234895b296d0Smrg			      pScrn->bitsPerPixel, 128, 4096,
234995b296d0Smrg			      pScrn->display->virtualX,
235095b296d0Smrg			      pScrn->display->virtualY,
235195b296d0Smrg			      pTrident->FbMapSize,
235295b296d0Smrg			      LOOKUP_BEST_REFRESH);
235395b296d0Smrg    } else {
235495b296d0Smrg	/*
235595b296d0Smrg	 * XXX Assuming min height 128, max 2048
235695b296d0Smrg	 */
235795b296d0Smrg	i = xf86ValidateModes(pScrn, pScrn->monitor->Modes,
235895b296d0Smrg			      pScrn->display->modes, clockRanges,
235995b296d0Smrg			      GetAccelPitchValues(pScrn), 0, 0,
236095b296d0Smrg			      pScrn->bitsPerPixel, 128, 2048,
236195b296d0Smrg			      pScrn->display->virtualX,
236295b296d0Smrg			      pScrn->display->virtualY,
236395b296d0Smrg			      pTrident->FbMapSize,
236495b296d0Smrg			      LOOKUP_BEST_REFRESH);
236595b296d0Smrg    }
236695b296d0Smrg
236795b296d0Smrg    if (i == -1) {
236895b296d0Smrg	if (IsPciCard && UseMMIO) {
236995b296d0Smrg    	    TRIDENTDisableMMIO(pScrn);
237095b296d0Smrg 	    TRIDENTUnmapMem(pScrn);
237195b296d0Smrg	}
237295b296d0Smrg	TRIDENTFreeRec(pScrn);
237395b296d0Smrg	return FALSE;
237495b296d0Smrg    }
237595b296d0Smrg
237695b296d0Smrg    /* Prune the modes marked as invalid */
237795b296d0Smrg    xf86PruneDriverModes(pScrn);
237895b296d0Smrg
237995b296d0Smrg    if (i == 0 || pScrn->modes == NULL) {
238095b296d0Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
238195b296d0Smrg	if (IsPciCard && UseMMIO) {
238295b296d0Smrg    	    TRIDENTDisableMMIO(pScrn);
238395b296d0Smrg 	    TRIDENTUnmapMem(pScrn);
238495b296d0Smrg	}
238595b296d0Smrg	TRIDENTFreeRec(pScrn);
238695b296d0Smrg	return FALSE;
238795b296d0Smrg    }
238895b296d0Smrg
238995b296d0Smrg    xf86SetCrtcForModes(pScrn, INTERLACE_HALVE_V);
239095b296d0Smrg
239195b296d0Smrg    /* Set the current mode to the first in the list */
239295b296d0Smrg    pScrn->currentMode = pScrn->modes;
239395b296d0Smrg
239495b296d0Smrg    /* Print the list of modes being used */
239595b296d0Smrg    xf86PrintModes(pScrn);
239695b296d0Smrg
239795b296d0Smrg    /* Set display resolution */
239895b296d0Smrg    xf86SetDpi(pScrn, 0, 0);
239995b296d0Smrg
240095b296d0Smrg    /* Load bpp-specific modules */
240195b296d0Smrg    switch (pScrn->bitsPerPixel) {
240295b296d0Smrg    case 8:
240395b296d0Smrg	pTrident->EngineOperation |= 0x00;
240495b296d0Smrg	break;
240595b296d0Smrg    case 16:
240695b296d0Smrg	pTrident->EngineOperation |= 0x01;
240795b296d0Smrg	break;
240895b296d0Smrg    case 24:
240995b296d0Smrg	pTrident->EngineOperation |= 0x03;
241095b296d0Smrg	break;
241195b296d0Smrg    case 32:
241295b296d0Smrg	pTrident->EngineOperation |= 0x02;
241395b296d0Smrg	break;
241495b296d0Smrg    }
241595b296d0Smrg
241695b296d0Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
241795b296d0Smrg	if (IsPciCard && UseMMIO) {
241895b296d0Smrg    	    TRIDENTDisableMMIO(pScrn);
241995b296d0Smrg 	    TRIDENTUnmapMem(pScrn);
242095b296d0Smrg	}
242195b296d0Smrg	TRIDENTFreeRec(pScrn);
242295b296d0Smrg	return FALSE;
242395b296d0Smrg    }
242495b296d0Smrg
242595b296d0Smrg    xf86LoaderReqSymLists(fbSymbols, NULL);
242695b296d0Smrg
242795b296d0Smrg    if (!xf86LoadSubModule(pScrn, "i2c")) {
242895b296d0Smrg	if (IsPciCard && UseMMIO) {
242995b296d0Smrg    	    TRIDENTDisableMMIO(pScrn);
243095b296d0Smrg 	    TRIDENTUnmapMem(pScrn);
243195b296d0Smrg	}
243295b296d0Smrg	TRIDENTFreeRec(pScrn);
243395b296d0Smrg	return FALSE;
243495b296d0Smrg    }
243595b296d0Smrg
243695b296d0Smrg    xf86LoaderReqSymLists(i2cSymbols, NULL);
243795b296d0Smrg
243895b296d0Smrg    /* Load shadow if needed */
243995b296d0Smrg    if (pTrident->ShadowFB) {
244095b296d0Smrg	if (!xf86LoadSubModule(pScrn, "shadow")) {
244195b296d0Smrg	    TRIDENTFreeRec(pScrn);
244295b296d0Smrg	    return FALSE;
244395b296d0Smrg	}
244495b296d0Smrg	xf86LoaderReqSymLists(shadowSymbols, NULL);
244595b296d0Smrg    }
244695b296d0Smrg
244795b296d0Smrg    /* Load XAA if needed */
244895b296d0Smrg    if (!pTrident->NoAccel) {
244995b296d0Smrg	if (!pTrident->useEXA) {
245095b296d0Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
245195b296d0Smrg		if (IsPciCard && UseMMIO) {
245295b296d0Smrg		    TRIDENTDisableMMIO(pScrn);
245395b296d0Smrg		    TRIDENTUnmapMem(pScrn);
245495b296d0Smrg		}
245595b296d0Smrg		TRIDENTFreeRec(pScrn);
245695b296d0Smrg		return FALSE;
245795b296d0Smrg	    }
245895b296d0Smrg	    xf86LoaderReqSymLists(xaaSymbols, NULL);
245995b296d0Smrg	}
246095b296d0Smrg
246195b296d0Smrg	if (pTrident->useEXA) {
246295b296d0Smrg	    XF86ModReqInfo req;
246395b296d0Smrg	    int errmaj, errmin;
246495b296d0Smrg
246595b296d0Smrg	    memset(&req, 0, sizeof(req));
246695b296d0Smrg
246795b296d0Smrg	    req.majorversion = 2;
246895b296d0Smrg            if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL, &req,
246995b296d0Smrg		&errmaj, &errmin))
247095b296d0Smrg	    {
247195b296d0Smrg		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
247295b296d0Smrg		if (IsPciCard && UseMMIO) {
247395b296d0Smrg		    TRIDENTDisableMMIO(pScrn);
247495b296d0Smrg		    TRIDENTUnmapMem(pScrn);
247595b296d0Smrg		}
247695b296d0Smrg		TRIDENTFreeRec(pScrn);
247795b296d0Smrg		return FALSE;
247895b296d0Smrg	    }
247995b296d0Smrg	    xf86LoaderReqSymLists(exaSymbols, NULL);
248095b296d0Smrg	}
248195b296d0Smrg
248295b296d0Smrg        switch (pScrn->displayWidth * pScrn->bitsPerPixel / 8) {
248395b296d0Smrg	    case 512:
248495b296d0Smrg	    case 8192:
248595b296d0Smrg		pTrident->EngineOperation |= 0x00;
248695b296d0Smrg		break;
248795b296d0Smrg	    case 1024:
248895b296d0Smrg		pTrident->EngineOperation |= 0x04;
248995b296d0Smrg		break;
249095b296d0Smrg	    case 2048:
249195b296d0Smrg		pTrident->EngineOperation |= 0x08;
249295b296d0Smrg		break;
249395b296d0Smrg	    case 4096:
249495b296d0Smrg		pTrident->EngineOperation |= 0x0C;
249595b296d0Smrg		break;
249695b296d0Smrg	}
249795b296d0Smrg    }
249895b296d0Smrg
249995b296d0Smrg    /* Load DDC if needed */
250095b296d0Smrg    /* This gives us DDC1 - we should be able to get DDC2B using i2c */
250195b296d0Smrg
250295b296d0Smrg    if (! ddcLoaded)
250395b296d0Smrg	if (!xf86LoadSubModule(pScrn, "ddc")) {
250495b296d0Smrg	    if (IsPciCard && UseMMIO) {
250595b296d0Smrg		TRIDENTDisableMMIO(pScrn);
250695b296d0Smrg		TRIDENTUnmapMem(pScrn);
250795b296d0Smrg	    }
250895b296d0Smrg	    TRIDENTFreeRec(pScrn);
250995b296d0Smrg	    return FALSE;
251095b296d0Smrg	}
251195b296d0Smrg
251295b296d0Smrg    xf86LoaderReqSymLists(ddcSymbols, NULL);
251395b296d0Smrg
251495b296d0Smrg    if (IsPciCard && UseMMIO) {
251595b296d0Smrg        TRIDENTDisableMMIO(pScrn);
251695b296d0Smrg	TRIDENTUnmapMem(pScrn);
251795b296d0Smrg    }
251895b296d0Smrg
251995b296d0Smrg    pScrn->racMemFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
252095b296d0Smrg
252195b296d0Smrg    if (pTrident->IsCyber && pTrident->MMIOonly)
252295b296d0Smrg	pScrn->racIoFlags = 0;
252395b296d0Smrg    else
252495b296d0Smrg	pScrn->racIoFlags = RAC_FB | RAC_COLORMAP | RAC_CURSOR | RAC_VIEWPORT;
252595b296d0Smrg
252695b296d0Smrg    pTrident->FbMapSize = pScrn->videoRam * 1024;
252795b296d0Smrg
252895b296d0Smrg    return TRUE;
252995b296d0Smrg}
253095b296d0Smrg
253195b296d0Smrg/*
253295b296d0Smrg * Map the framebuffer and MMIO memory.
253395b296d0Smrg */
253495b296d0Smrg
253595b296d0Smrgstatic Bool
253695b296d0SmrgTRIDENTMapMem(ScrnInfoPtr pScrn)
253795b296d0Smrg{
253895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
253995b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
254095b296d0Smrg    int mapsize = 0x10000;
254195b296d0Smrg
254295b296d0Smrg    if (Is3Dchip) mapsize = 0x20000;
254395b296d0Smrg
254495b296d0Smrg    if (IsPciCard && UseMMIO)
254595b296d0Smrg    	pTrident->IOBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO,
254695b296d0Smrg		pTrident->PciTag, pTrident->IOAddress, mapsize);
254795b296d0Smrg    else {
254895b296d0Smrg    	pTrident->IOBase = xf86MapDomainMemory(pScrn->scrnIndex, VIDMEM_MMIO,
254995b296d0Smrg		pTrident->PciTag, pTrident->IOAddress, 0x1000);
255095b296d0Smrg    	pTrident->IOBase += 0xF00;
255195b296d0Smrg    }
255295b296d0Smrg
255395b296d0Smrg    if (pTrident->IOBase == NULL)
255495b296d0Smrg	return FALSE;
255595b296d0Smrg
255695b296d0Smrg    if (pTrident->Linear) {
255795b296d0Smrg        if (pTrident->FbMapSize != 0) {
255895b296d0Smrg	    pTrident->FbBase = xf86MapPciMem(pScrn->scrnIndex,
255995b296d0Smrg				VIDMEM_FRAMEBUFFER,
256095b296d0Smrg				 pTrident->PciTag,
256195b296d0Smrg				 (unsigned long)pTrident->FbAddress,
256295b296d0Smrg				 pTrident->FbMapSize);
256395b296d0Smrg	    if (pTrident->FbBase == NULL)
256495b296d0Smrg		return FALSE;
256595b296d0Smrg    	}
256695b296d0Smrg    }
256795b296d0Smrg    else
256895b296d0Smrg	pTrident->FbBase = hwp->Base;
256995b296d0Smrg
257095b296d0Smrg    return TRUE;
257195b296d0Smrg}
257295b296d0Smrg
257395b296d0Smrg/*
257495b296d0Smrg * Unmap the framebuffer and MMIO memory.
257595b296d0Smrg */
257695b296d0Smrg
257795b296d0Smrgstatic Bool
257895b296d0SmrgTRIDENTUnmapMem(ScrnInfoPtr pScrn)
257995b296d0Smrg{
258095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
258195b296d0Smrg    int mapsize = 0x10000;
258295b296d0Smrg
258395b296d0Smrg    if (Is3Dchip) mapsize = 0x20000;
258495b296d0Smrg
258595b296d0Smrg    /*
258695b296d0Smrg     * Unmap IO registers to virtual address space
258795b296d0Smrg     */
258895b296d0Smrg    if (IsPciCard && UseMMIO)
258995b296d0Smrg    	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, mapsize);
259095b296d0Smrg    else {
259195b296d0Smrg    	pTrident->IOBase -= 0xF00;
259295b296d0Smrg    	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->IOBase, 0x1000);
259395b296d0Smrg    }
259495b296d0Smrg    pTrident->IOBase = NULL;
259595b296d0Smrg
259695b296d0Smrg    if (pTrident->Linear) {
259795b296d0Smrg    	if (pTrident->FbMapSize != 0) {
259895b296d0Smrg    	    xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pTrident->FbBase,
259995b296d0Smrg							pTrident->FbMapSize);
260095b296d0Smrg    	pTrident->FbBase = NULL;
260195b296d0Smrg        }
260295b296d0Smrg    }
260395b296d0Smrg
260495b296d0Smrg    return TRUE;
260595b296d0Smrg}
260695b296d0Smrg
260795b296d0Smrg
260895b296d0Smrg/*
260995b296d0Smrg * This function saves the video state.
261095b296d0Smrg */
261195b296d0Smrgstatic void
261295b296d0SmrgTRIDENTSave(ScrnInfoPtr pScrn)
261395b296d0Smrg{
261495b296d0Smrg    TRIDENTPtr pTrident;
261595b296d0Smrg    vgaRegPtr vgaReg;
261695b296d0Smrg    TRIDENTRegPtr tridentReg;
261795b296d0Smrg
261895b296d0Smrg    pTrident = TRIDENTPTR(pScrn);
261995b296d0Smrg    vgaReg = &VGAHWPTR(pScrn)->SavedReg;
262095b296d0Smrg    tridentReg = &pTrident->SavedReg;
262195b296d0Smrg
262295b296d0Smrg    vgaHWSave(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP |
262395b296d0Smrg			     (IsPrimaryCard ? VGA_SR_FONTS : 0));
262495b296d0Smrg
262595b296d0Smrg    if (pScrn->progClock)
262695b296d0Smrg    	TridentSave(pScrn, tridentReg);
262795b296d0Smrg    else
262895b296d0Smrg    	TVGASave(pScrn, tridentReg);
262995b296d0Smrg
263095b296d0Smrg    if (pTrident->TVChipset != 0)
263195b296d0Smrg       VIA_SaveTVDepentVGAReg(pScrn);
263295b296d0Smrg}
263395b296d0Smrg
263495b296d0Smrg
263595b296d0Smrg/*
263695b296d0Smrg * Initialise a new mode.  This is currently still using the old
263795b296d0Smrg * "initialise struct, restore/write struct to HW" model.  That could
263895b296d0Smrg * be changed.
263995b296d0Smrg */
264095b296d0Smrg
264195b296d0Smrgstatic Bool
264295b296d0SmrgTRIDENTModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
264395b296d0Smrg{
264495b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
264595b296d0Smrg    vgaRegPtr vgaReg;
264695b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
264795b296d0Smrg    TRIDENTRegPtr tridentReg;
264895b296d0Smrg
264995b296d0Smrg    WAITFORVSYNC;
265095b296d0Smrg
265195b296d0Smrg    TridentFindClock(pScrn,mode->Clock);
265295b296d0Smrg
265395b296d0Smrg    switch (pTrident->Chipset) {
265495b296d0Smrg	case TGUI9660:
265595b296d0Smrg	case TGUI9680:
265695b296d0Smrg	case PROVIDIA9682:
265795b296d0Smrg	case PROVIDIA9685:
265895b296d0Smrg	case IMAGE975:
265995b296d0Smrg	case IMAGE985:
266095b296d0Smrg	case BLADE3D:
266195b296d0Smrg	case CYBERBLADEI7:
266295b296d0Smrg	case CYBERBLADEI7D:
266395b296d0Smrg	case CYBERBLADEI1:
266495b296d0Smrg	case CYBERBLADEI1D:
266595b296d0Smrg	case CYBERBLADEAI1:
266695b296d0Smrg	case CYBERBLADEAI1D:
266795b296d0Smrg	case CYBER9520:
266895b296d0Smrg	case CYBER9525DVD:
266995b296d0Smrg	case CYBERBLADEE4:
267095b296d0Smrg	case CYBER9397:
267195b296d0Smrg	case CYBER9397DVD:
267295b296d0Smrg	case BLADEXP:
267395b296d0Smrg	case CYBERBLADEXPAI1:
267495b296d0Smrg	case CYBERBLADEXP4:
267595b296d0Smrg	case XP5:
267695b296d0Smrg	    /* Get ready for MUX mode */
267795b296d0Smrg	    if (pTrident->MUX &&
267895b296d0Smrg		pScrn->bitsPerPixel == 8 &&
267995b296d0Smrg		!mode->CrtcHAdjusted) {
268095b296d0Smrg		ErrorF("BARF\n");
268195b296d0Smrg		mode->CrtcHDisplay >>= 1;
268295b296d0Smrg		mode->CrtcHSyncStart >>= 1;
268395b296d0Smrg		mode->CrtcHSyncEnd >>= 1;
268495b296d0Smrg		mode->CrtcHBlankStart >>= 1;
268595b296d0Smrg		mode->CrtcHBlankEnd >>= 1;
268695b296d0Smrg		mode->CrtcHTotal >>= 1;
268795b296d0Smrg		mode->CrtcHAdjusted = TRUE;
268895b296d0Smrg	    }
268995b296d0Smrg	    break;
269095b296d0Smrg	default:
269195b296d0Smrg	    if (pScrn->videoRam < 1024 &&
269295b296d0Smrg		!mode->CrtcHAdjusted) {
269395b296d0Smrg		mode->CrtcHDisplay <<= 1;
269495b296d0Smrg		mode->CrtcHSyncStart <<= 1;
269595b296d0Smrg		mode->CrtcHSyncEnd <<= 1;
269695b296d0Smrg		mode->CrtcHBlankStart <<= 1;
269795b296d0Smrg		mode->CrtcHBlankEnd <<= 1;
269895b296d0Smrg		mode->CrtcHTotal <<= 1;
269995b296d0Smrg		mode->CrtcHAdjusted = TRUE;
270095b296d0Smrg	    }
270195b296d0Smrg	    break;
270295b296d0Smrg    }
270395b296d0Smrg
270495b296d0Smrg    vgaHWUnlock(hwp);
270595b296d0Smrg    /* Initialise the ModeReg values */
270695b296d0Smrg    if (!vgaHWInit(pScrn, mode))
270795b296d0Smrg	return FALSE;
270895b296d0Smrg
270995b296d0Smrg    pScrn->vtSema = TRUE;
271095b296d0Smrg    /*
271195b296d0Smrg     * We used to do this at a later time.
271295b296d0Smrg     * Now since READOUT isn't defined any more
271395b296d0Smrg     * we do it here.
271495b296d0Smrg     * The original NOTE read:
271595b296d0Smrg     * TridentInit() has to modify registers
271695b296d0Smrg     * that have already been set by vgaHWRestore().
271795b296d0Smrg     * So we call it _after_ vgaHWRestore() has
271895b296d0Smrg     * programmed these registers.
271995b296d0Smrg     */
272095b296d0Smrg    if (pScrn->progClock) {
272195b296d0Smrg    	if (!TridentInit(pScrn, mode))
272295b296d0Smrg	    return FALSE;
272395b296d0Smrg    } else {
272495b296d0Smrg    	if (!TVGAInit(pScrn, mode))
272595b296d0Smrg	    return FALSE;
272695b296d0Smrg    }
272795b296d0Smrg
272895b296d0Smrg    /* Program the registers */
272995b296d0Smrg    vgaHWProtect(pScrn, TRUE);
273095b296d0Smrg    vgaReg = &hwp->ModeReg;
273195b296d0Smrg    tridentReg = &pTrident->ModeReg;
273295b296d0Smrg
273395b296d0Smrg    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE);
273495b296d0Smrg    if (pScrn->progClock)
273595b296d0Smrg    	TridentRestore(pScrn, tridentReg);
273695b296d0Smrg    else
273795b296d0Smrg	TVGARestore(pScrn, tridentReg);
273895b296d0Smrg
273995b296d0Smrg    vgaHWProtect(pScrn, FALSE);
274095b296d0Smrg
274195b296d0Smrg    if (xf86IsPc98())
274295b296d0Smrg	PC98TRIDENTEnable(pScrn);
274395b296d0Smrg
274495b296d0Smrg    if (pTrident->TVChipset != 0)
274595b296d0Smrg       VIA_TVInit(pScrn);
274695b296d0Smrg
274795b296d0Smrg    return TRUE;
274895b296d0Smrg}
274995b296d0Smrg
275095b296d0Smrg/*
275195b296d0Smrg * Restore the initial (text) mode.
275295b296d0Smrg */
275395b296d0Smrgstatic void
275495b296d0SmrgTRIDENTRestore(ScrnInfoPtr pScrn)
275595b296d0Smrg{
275695b296d0Smrg    vgaHWPtr hwp;
275795b296d0Smrg    vgaRegPtr vgaReg;
275895b296d0Smrg    TRIDENTPtr pTrident;
275995b296d0Smrg    TRIDENTRegPtr tridentReg;
276095b296d0Smrg
276195b296d0Smrg    hwp = VGAHWPTR(pScrn);
276295b296d0Smrg    pTrident = TRIDENTPTR(pScrn);
276395b296d0Smrg    vgaReg = &hwp->SavedReg;
276495b296d0Smrg    tridentReg = &pTrident->SavedReg;
276595b296d0Smrg
276695b296d0Smrg    vgaHWProtect(pScrn, TRUE);
276795b296d0Smrg
276895b296d0Smrg    if (pScrn->progClock)
276995b296d0Smrg    	TridentRestore(pScrn, tridentReg);
277095b296d0Smrg    else
277195b296d0Smrg	TVGARestore(pScrn, tridentReg);
277295b296d0Smrg
277395b296d0Smrg    vgaHWRestore(pScrn, vgaReg, VGA_SR_MODE | VGA_SR_CMAP |
277495b296d0Smrg				(IsPrimaryCard ? VGA_SR_FONTS : 0));
277595b296d0Smrg
277695b296d0Smrg    if (pTrident->TVChipset != 0)
277795b296d0Smrg       VIA_RestoreTVDependVGAReg(pScrn);
277895b296d0Smrg
277995b296d0Smrg    vgaHWProtect(pScrn, FALSE);
278095b296d0Smrg}
278195b296d0Smrg
278295b296d0Smrg
278395b296d0Smrg/* Mandatory */
278495b296d0Smrg
278595b296d0Smrg/* This gets called at the start of each server generation */
278695b296d0Smrg
278795b296d0Smrgstatic Bool
278895b296d0SmrgTRIDENTScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
278995b296d0Smrg{
279095b296d0Smrg    /* The vgaHW references will disappear one day */
279195b296d0Smrg    ScrnInfoPtr pScrn;
279295b296d0Smrg    vgaHWPtr hwp;
279395b296d0Smrg    TRIDENTPtr pTrident;
279495b296d0Smrg    int ret;
279595b296d0Smrg    VisualPtr visual;
279695b296d0Smrg    unsigned char *FBStart;
279795b296d0Smrg    int width, height, displayWidth;
279895b296d0Smrg
279995b296d0Smrg    /*
280095b296d0Smrg     * First get the ScrnInfoRec
280195b296d0Smrg     */
280295b296d0Smrg    pScrn = xf86Screens[pScreen->myNum];
280395b296d0Smrg    pTrident = TRIDENTPTR(pScrn);
280495b296d0Smrg
280595b296d0Smrg    if (IsPrimaryCard) {
280695b296d0Smrg	if (!vgaHWMapMem(pScrn))
280795b296d0Smrg   	    return FALSE;
280895b296d0Smrg    }
280995b296d0Smrg
281095b296d0Smrg    /* Map the TRIDENT memory and MMIO areas */
281195b296d0Smrg    if (!TRIDENTMapMem(pScrn))
281295b296d0Smrg	return FALSE;
281395b296d0Smrg
281495b296d0Smrg    if (!xf86IsPc98()) {
281595b296d0Smrg#ifdef VBE_INFO
281695b296d0Smrg	if (pTrident->vbeModes) {
281795b296d0Smrg	    pTrident->pVbe = VBEInit(NULL,pTrident->pEnt->index);
281895b296d0Smrg	    pTrident->Int10 = pTrident->pVbe->pInt10;
281995b296d0Smrg	} else
282095b296d0Smrg#endif
282195b296d0Smrg	{
282295b296d0Smrg	    if (xf86LoadSubModule(pScrn, "int10")) {
282395b296d0Smrg		xf86LoaderReqSymLists(int10Symbols, NULL);
282495b296d0Smrg		xf86DrvMsg(pScrn->scrnIndex,X_INFO,"Initializing int10\n");
282595b296d0Smrg		pTrident->Int10 = xf86InitInt10(pTrident->pEnt->index);
282695b296d0Smrg	    }
282795b296d0Smrg	}
282895b296d0Smrg    }
282995b296d0Smrg
283095b296d0Smrg    hwp = VGAHWPTR(pScrn);
283195b296d0Smrg
283295b296d0Smrg    if (IsPciCard && UseMMIO) {
283395b296d0Smrg    	TRIDENTEnableMMIO(pScrn);
283495b296d0Smrg
283595b296d0Smrg    	/* Initialize the MMIO vgahw functions */
283695b296d0Smrg    	vgaHWSetMmioFuncs(hwp, pTrident->IOBase, 0);
283795b296d0Smrg    }
283895b296d0Smrg
283995b296d0Smrg    /* Save the current state */
284095b296d0Smrg    TRIDENTSave(pScrn);
284195b296d0Smrg
284295b296d0Smrg    /*
284395b296d0Smrg     * Some Trident chip on PC-9821 needs setup,
284495b296d0Smrg     * because VGA chip is not initialized by VGA BIOS.
284595b296d0Smrg     */
284695b296d0Smrg    if (IsPciCard && xf86IsPc98()) {
284795b296d0Smrg	 PC98TRIDENTInit(pScrn);
284895b296d0Smrg    } else tridentSetModeBIOS(pScrn,pScrn->currentMode);
284995b296d0Smrg
285095b296d0Smrg    /* Initialise the first mode */
285195b296d0Smrg    if (!TRIDENTModeInit(pScrn, pScrn->currentMode))
285295b296d0Smrg	return FALSE;
285395b296d0Smrg
285495b296d0Smrg    /* Darken the screen for aesthetic reasons and set the viewport */
285595b296d0Smrg    TRIDENTSaveScreen(pScreen, SCREEN_SAVER_ON);
285695b296d0Smrg    TRIDENTAdjustFrame(scrnIndex, pScrn->frameX0, pScrn->frameY0, 0);
285795b296d0Smrg
285895b296d0Smrg    /*
285995b296d0Smrg     * The next step is to setup the screen's visuals, and initialise the
286095b296d0Smrg     * framebuffer code.  In cases where the framebuffer's default
286195b296d0Smrg     * choices for things like visual layouts and bits per RGB are OK,
286295b296d0Smrg     * this may be as simple as calling the framebuffer's ScreenInit()
286395b296d0Smrg     * function.  If not, the visuals will need to be setup before calling
286495b296d0Smrg     * a fb ScreenInit() function and fixed up after.
286595b296d0Smrg     *
286695b296d0Smrg     * For most PC hardware at depths >= 8, the defaults that fb uses
286795b296d0Smrg     * are not appropriate.  In this driver, we fixup the visuals after.
286895b296d0Smrg     */
286995b296d0Smrg
287095b296d0Smrg    /*
287195b296d0Smrg     * Reset visual list.
287295b296d0Smrg     */
287395b296d0Smrg    miClearVisualTypes();
287495b296d0Smrg
287595b296d0Smrg    /* Setup the visuals we support. */
287695b296d0Smrg
287795b296d0Smrg    if (!miSetVisualTypes(pScrn->depth,
287895b296d0Smrg			  miGetDefaultVisualMask(pScrn->depth),
287995b296d0Smrg			  pScrn->rgbBits, pScrn->defaultVisual)) {
288095b296d0Smrg	if (pTrident->pVbe)
288195b296d0Smrg	    	vbeFree(pTrident->pVbe);
288295b296d0Smrg	else
288395b296d0Smrg	    xf86FreeInt10(pTrident->Int10);
288495b296d0Smrg      return FALSE;
288595b296d0Smrg    }
288695b296d0Smrg
288795b296d0Smrg    miSetPixmapDepths ();
288895b296d0Smrg
288995b296d0Smrg    /* FIXME - we don't do shadowfb for < 4 */
289095b296d0Smrg    displayWidth = pScrn->displayWidth;
289195b296d0Smrg    if (pTrident->Rotate) {
289295b296d0Smrg	height = pScrn->virtualX;
289395b296d0Smrg	width = pScrn->virtualY;
289495b296d0Smrg    } else {
289595b296d0Smrg	width = pScrn->virtualX;
289695b296d0Smrg	height = pScrn->virtualY;
289795b296d0Smrg    }
289895b296d0Smrg
289995b296d0Smrg    if(pTrident->ShadowFB) {
290095b296d0Smrg 	pTrident->ShadowPitch = BitmapBytePad(pScrn->bitsPerPixel * width);
290195b296d0Smrg        pTrident->ShadowPtr = xalloc(pTrident->ShadowPitch * height);
290295b296d0Smrg	displayWidth = pTrident->ShadowPitch / (pScrn->bitsPerPixel >> 3);
290395b296d0Smrg        FBStart = pTrident->ShadowPtr;
290495b296d0Smrg    } else {
290595b296d0Smrg	pTrident->ShadowFB = FALSE;
290695b296d0Smrg	pTrident->ShadowPtr = NULL;
290795b296d0Smrg	FBStart = pTrident->FbBase;
290895b296d0Smrg    }
290995b296d0Smrg
291095b296d0Smrg    /*
291195b296d0Smrg     * Call the framebuffer layer's ScreenInit function, and fill in other
291295b296d0Smrg     * pScreen fields.
291395b296d0Smrg     */
291495b296d0Smrg
291595b296d0Smrg    switch (pScrn->bitsPerPixel) {
291695b296d0Smrg    case 8:
291795b296d0Smrg    case 16:
291895b296d0Smrg    case 24:
291995b296d0Smrg    case 32:
292095b296d0Smrg	ret = fbScreenInit(pScreen, FBStart, width,
292195b296d0Smrg			height, pScrn->xDpi, pScrn->yDpi,
292295b296d0Smrg			displayWidth, pScrn->bitsPerPixel);
292395b296d0Smrg
292495b296d0Smrg	break;
292595b296d0Smrg    default:
292695b296d0Smrg	xf86DrvMsg(scrnIndex, X_ERROR,
292795b296d0Smrg		   "Internal error: invalid bpp (%d) in TRIDENTScrnInit\n",
292895b296d0Smrg		   pScrn->bitsPerPixel);
292995b296d0Smrg	    ret = FALSE;
293095b296d0Smrg	break;
293195b296d0Smrg    }
293295b296d0Smrg    if (!ret) {
293395b296d0Smrg	if (pTrident->pVbe)
293495b296d0Smrg	    vbeFree(pTrident->pVbe);
293595b296d0Smrg	else
293695b296d0Smrg	    xf86FreeInt10(pTrident->Int10);
293795b296d0Smrg	return FALSE;
293895b296d0Smrg    }
293995b296d0Smrg    if (pScrn->bitsPerPixel > 8) {
294095b296d0Smrg        /* Fixup RGB ordering */
294195b296d0Smrg        visual = pScreen->visuals + pScreen->numVisuals;
294295b296d0Smrg        while (--visual >= pScreen->visuals) {
294395b296d0Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
294495b296d0Smrg		visual->offsetRed = pScrn->offset.red;
294595b296d0Smrg		visual->offsetGreen = pScrn->offset.green;
294695b296d0Smrg		visual->offsetBlue = pScrn->offset.blue;
294795b296d0Smrg		visual->redMask = pScrn->mask.red;
294895b296d0Smrg		visual->greenMask = pScrn->mask.green;
294995b296d0Smrg		visual->blueMask = pScrn->mask.blue;
295095b296d0Smrg	    }
295195b296d0Smrg	}
295295b296d0Smrg    }
295395b296d0Smrg
295495b296d0Smrg    /* must be after RGB ordering fixed */
295595b296d0Smrg    fbPictureInit (pScreen, 0, 0);
295695b296d0Smrg
295795b296d0Smrg    xf86SetBlackWhitePixels(pScreen);
295895b296d0Smrg
295995b296d0Smrg    pTrident->BlockHandler = pScreen->BlockHandler;
296095b296d0Smrg    pScreen->BlockHandler = TRIDENTBlockHandler;
296195b296d0Smrg
296295b296d0Smrg    if (!pTrident->ShadowFB)
296395b296d0Smrg	TRIDENTDGAInit(pScreen);
296495b296d0Smrg
296595b296d0Smrg    if (!pTrident->Linear) {
296695b296d0Smrg	miBankInfoPtr pBankInfo;
296795b296d0Smrg
296895b296d0Smrg	/* Setup the vga banking variables */
296995b296d0Smrg	pBankInfo = xnfcalloc(sizeof(miBankInfoRec),1);
297095b296d0Smrg	if (pBankInfo == NULL) {
297195b296d0Smrg	    if (pTrident->pVbe)
297295b296d0Smrg		vbeFree(pTrident->pVbe);
297395b296d0Smrg	    else
297495b296d0Smrg		xf86FreeInt10(pTrident->Int10);
297595b296d0Smrg	    return FALSE;
297695b296d0Smrg	}
297795b296d0Smrg	pBankInfo->pBankA = pTrident->FbBase;
297895b296d0Smrg	pBankInfo->pBankB = pTrident->FbBase;
297995b296d0Smrg	pBankInfo->BankSize = 0x10000;
298095b296d0Smrg	pBankInfo->nBankDepth = (pScrn->depth == 4) ? 1 : pScrn->depth;
298195b296d0Smrg
298295b296d0Smrg	pBankInfo->SetSourceBank =
298395b296d0Smrg		(miBankProcPtr)TVGA8900SetRead;
298495b296d0Smrg	pBankInfo->SetDestinationBank =
298595b296d0Smrg		(miBankProcPtr)TVGA8900SetWrite;
298695b296d0Smrg	pBankInfo->SetSourceAndDestinationBanks =
298795b296d0Smrg		(miBankProcPtr)TVGA8900SetReadWrite;
298895b296d0Smrg	if (!miInitializeBanking(pScreen, pScrn->virtualX, pScrn->virtualY,
298995b296d0Smrg				 pScrn->displayWidth, pBankInfo)) {
299095b296d0Smrg	    xfree(pBankInfo);
299195b296d0Smrg	    pBankInfo = NULL;
299295b296d0Smrg	    if (pTrident->pVbe)
299395b296d0Smrg	    	vbeFree(pTrident->pVbe);
299495b296d0Smrg	    else
299595b296d0Smrg		xf86FreeInt10(pTrident->Int10);
299695b296d0Smrg	    return FALSE;
299795b296d0Smrg	}
299895b296d0Smrg    }
299995b296d0Smrg
300095b296d0Smrg    {
300195b296d0Smrg    	BoxRec AvailFBArea;
300295b296d0Smrg
300395b296d0Smrg	AvailFBArea.x1 = 0;
300495b296d0Smrg    	AvailFBArea.y1 = 0;
300595b296d0Smrg    	AvailFBArea.x2 = pScrn->displayWidth;
300695b296d0Smrg    	AvailFBArea.y2 = pTrident->FbMapSize / (pScrn->displayWidth *
300795b296d0Smrg					    pScrn->bitsPerPixel / 8);
300895b296d0Smrg
300995b296d0Smrg    	if (AvailFBArea.y2 > 2047) AvailFBArea.y2 = 2047;
301095b296d0Smrg
301195b296d0Smrg    	if (xf86InitFBManager(pScreen, &AvailFBArea)) {
301295b296d0Smrg	    int cpp = pScrn->bitsPerPixel / 8;
301395b296d0Smrg	    int area = AvailFBArea.y2 * pScrn->displayWidth;
301495b296d0Smrg	    int areaoffset = area * cpp;
301595b296d0Smrg
301695b296d0Smrg    	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
301795b296d0Smrg	       "Using %i scanlines of offscreen memory for area's \n",
301895b296d0Smrg 	       AvailFBArea.y2 - pScrn->virtualY);
301995b296d0Smrg
302095b296d0Smrg	    if (xf86InitFBManagerLinear(pScreen, area, ((pTrident->FbMapSize/cpp) - area))) {
302195b296d0Smrg		xf86DrvMsg(scrnIndex, X_INFO,
302295b296d0Smrg			"Using %ld bytes of offscreen memory for linear (offset=0x%x)\n", (pTrident->FbMapSize - areaoffset), areaoffset);
302395b296d0Smrg	    }
302495b296d0Smrg    	}
302595b296d0Smrg    }
302695b296d0Smrg
302795b296d0Smrg    if (Is3Dchip) {
302895b296d0Smrg	if ((pTrident->Chipset == CYBERBLADEI7) ||
302995b296d0Smrg	    (pTrident->Chipset == CYBERBLADEI7D) ||
303095b296d0Smrg	    (pTrident->Chipset == CYBERBLADEI1) ||
303195b296d0Smrg	    (pTrident->Chipset == CYBERBLADEI1D) ||
303295b296d0Smrg	    (pTrident->Chipset == CYBERBLADEAI1) ||
303395b296d0Smrg	    (pTrident->Chipset == CYBERBLADEAI1D) ||
303495b296d0Smrg	    (pTrident->Chipset == CYBERBLADEE4) ||
303595b296d0Smrg	    (pTrident->Chipset == BLADE3D)) {
303695b296d0Smrg	    if (pTrident->useEXA)
303795b296d0Smrg		BladeExaInit(pScreen);
303895b296d0Smrg	    else
303995b296d0Smrg		BladeXaaInit(pScreen);
304095b296d0Smrg	} else
304195b296d0Smrg	if ((pTrident->Chipset == CYBERBLADEXP4) ||
304295b296d0Smrg	    (pTrident->Chipset == XP5)) {
304395b296d0Smrg	    if (pTrident->useEXA)
304495b296d0Smrg	    	XP4ExaInit(pScreen);
304595b296d0Smrg	    else
304695b296d0Smrg		XP4XaaInit(pScreen);
304795b296d0Smrg	} else
304895b296d0Smrg	if ((pTrident->Chipset == BLADEXP) ||
304995b296d0Smrg	    (pTrident->Chipset == CYBERBLADEXPAI1)) {
305095b296d0Smrg		XPAccelInit(pScreen);
305195b296d0Smrg	} else {
305295b296d0Smrg	    	ImageAccelInit(pScreen);
305395b296d0Smrg	}
305495b296d0Smrg    } else {
305595b296d0Smrg    	TridentAccelInit(pScreen);
305695b296d0Smrg    }
305795b296d0Smrg
305895b296d0Smrg    miInitializeBackingStore(pScreen);
305995b296d0Smrg    xf86SetBackingStore(pScreen);
306095b296d0Smrg
306195b296d0Smrg    /* Initialise cursor functions */
306295b296d0Smrg    miDCInitialize (pScreen, xf86GetPointerScreenFuncs());
306395b296d0Smrg
306495b296d0Smrg    if (pTrident->HWCursor) {
306595b296d0Smrg        xf86SetSilkenMouse(pScreen);
306695b296d0Smrg	TridentHWCursorInit(pScreen);
306795b296d0Smrg    }
306895b296d0Smrg
306995b296d0Smrg    /* Initialise default colourmap */
307095b296d0Smrg    if (!miCreateDefColormap(pScreen)) {
307195b296d0Smrg	if (pTrident->pVbe)
307295b296d0Smrg	    vbeFree(pTrident->pVbe);
307395b296d0Smrg	else
307495b296d0Smrg	    xf86FreeInt10(pTrident->Int10);
307595b296d0Smrg	return FALSE;
307695b296d0Smrg    }
307795b296d0Smrg    if(!xf86HandleColormaps(pScreen, 256, 6, TridentLoadPalette,
307895b296d0Smrg			    TridentSetOverscan, CMAP_RELOAD_ON_MODE_SWITCH|CMAP_PALETTED_TRUECOLOR)) {
307995b296d0Smrg	if (pTrident->pVbe)
308095b296d0Smrg	    vbeFree(pTrident->pVbe);
308195b296d0Smrg	else
308295b296d0Smrg	    xf86FreeInt10(pTrident->Int10);
308395b296d0Smrg	return FALSE;
308495b296d0Smrg    }
308595b296d0Smrg    if(pTrident->ShadowFB) {
308695b296d0Smrg        if(pTrident->Rotate) {
308795b296d0Smrg	    if (!pTrident->PointerMoved) {
308895b296d0Smrg	        pTrident->PointerMoved = pScrn->PointerMoved;
308995b296d0Smrg		pScrn->PointerMoved = TRIDENTPointerMoved;
309095b296d0Smrg	    }
309195b296d0Smrg	    switch (pScrn->bitsPerPixel) {
309295b296d0Smrg	    case 8:    pTrident->RefreshArea = TRIDENTRefreshArea8; break;
309395b296d0Smrg	    case 16:   pTrident->RefreshArea = TRIDENTRefreshArea16; break;
309495b296d0Smrg	    case 24:   pTrident->RefreshArea = TRIDENTRefreshArea24; break;
309595b296d0Smrg	    case 32:   pTrident->RefreshArea = TRIDENTRefreshArea32; break;
309695b296d0Smrg	    }
309795b296d0Smrg	} else {
309895b296d0Smrg	  pTrident->RefreshArea = TRIDENTRefreshArea;
309995b296d0Smrg	}
310095b296d0Smrg	shadowInit (pScreen, TRIDENTShadowUpdate, 0);
310195b296d0Smrg    }
310295b296d0Smrg
310395b296d0Smrg    xf86DPMSInit(pScreen, (DPMSSetProcPtr)TRIDENTDisplayPowerManagementSet, 0);
310495b296d0Smrg
310595b296d0Smrg    pScrn->memPhysBase = pTrident->FbAddress;
310695b296d0Smrg    pScrn->fbOffset = 0;
310795b296d0Smrg
310895b296d0Smrg    if (pTrident->Chipset >= TGUI9660)
310995b296d0Smrg	TRIDENTInitVideo(pScreen);
311095b296d0Smrg
311195b296d0Smrg    pTrident->CloseScreen = pScreen->CloseScreen;
311295b296d0Smrg    pScreen->CloseScreen = TRIDENTCloseScreen;
311395b296d0Smrg    pScreen->SaveScreen = TRIDENTSaveScreen;
311495b296d0Smrg
311595b296d0Smrg    /* Report any unused options (only for the first generation) */
311695b296d0Smrg    if (serverGeneration == 1) {
311795b296d0Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
311895b296d0Smrg    }
311995b296d0Smrg
312095b296d0Smrg#if 0
312195b296d0Smrg    TRIDENTI2CInit(pScreen);
312295b296d0Smrg
312395b296d0Smrg    xf86PrintEDID(xf86DoEDID_DDC2(pScrn->scrnIndex,pTrident->DDC));
312495b296d0Smrg#endif
312595b296d0Smrg
312695b296d0Smrg    return TRUE;
312795b296d0Smrg}
312895b296d0Smrg
312995b296d0Smrg/* Usually mandatory */
313095b296d0SmrgBool
313195b296d0SmrgTRIDENTSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
313295b296d0Smrg{
313395b296d0Smrg    return TRIDENTModeInit(xf86Screens[scrnIndex], mode);
313495b296d0Smrg}
313595b296d0Smrg
313695b296d0Smrg
313795b296d0Smrg/*
313895b296d0Smrg * This function is used to initialize the Start Address - the first
313995b296d0Smrg * displayed location in the video memory.
314095b296d0Smrg */
314195b296d0Smrg/* Usually mandatory */
314295b296d0Smrgvoid
314395b296d0SmrgTRIDENTAdjustFrame(int scrnIndex, int x, int y, int flags)
314495b296d0Smrg{
314595b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
314695b296d0Smrg    TRIDENTPtr pTrident;
314795b296d0Smrg    int base = y * pScrn->displayWidth + x;
314895b296d0Smrg    int vgaIOBase;
314995b296d0Smrg    CARD8 temp;
315095b296d0Smrg
315195b296d0Smrg    pTrident = TRIDENTPTR(pScrn);
315295b296d0Smrg    vgaIOBase = VGAHWPTR(pScrn)->IOBase;
315395b296d0Smrg
315495b296d0Smrg    switch (pScrn->bitsPerPixel) {
315595b296d0Smrg	case 8:
315695b296d0Smrg	    if (pScrn->progClock)
315795b296d0Smrg	    	base = (base & 0xFFFFFFF8) >> 2;
315895b296d0Smrg	    else
315995b296d0Smrg	    	base = (base & 0xFFFFFFF8) >> 3;
316095b296d0Smrg	    break;
316195b296d0Smrg	case 16:
316295b296d0Smrg	    base >>= 1;
316395b296d0Smrg	    break;
316495b296d0Smrg	case 24:
316595b296d0Smrg	    base = (((base + 1) & ~0x03) * 3) >> 2;
316695b296d0Smrg	    break;
316795b296d0Smrg	case 32:
316895b296d0Smrg	    break;
316995b296d0Smrg    }
317095b296d0Smrg
317195b296d0Smrg    /* CRT bits 0-15 */
317295b296d0Smrg    OUTW(vgaIOBase + 4, (base & 0x00FF00) | 0x0C);
317395b296d0Smrg    OUTW(vgaIOBase + 4, ((base & 0x00FF) << 8) | 0x0D);
317495b296d0Smrg    /* CRT bit 16 */
317595b296d0Smrg    OUTB(vgaIOBase + 4, CRTCModuleTest); temp = INB(vgaIOBase + 5) & 0xDF;
317695b296d0Smrg    OUTB(vgaIOBase + 5, temp | ((base & 0x10000) >> 11));
317795b296d0Smrg    /* CRT bit 17-19 */
317895b296d0Smrg    OUTB(vgaIOBase + 4, CRTHiOrd); temp = INB(vgaIOBase + 5) & 0xF8;
317995b296d0Smrg    OUTB(vgaIOBase + 5, temp | ((base & 0xE0000) >> 17));
318095b296d0Smrg}
318195b296d0Smrg
318295b296d0Smrg
318395b296d0Smrg/*
318495b296d0Smrg * This is called when VT switching back to the X server.  Its job is
318595b296d0Smrg * to reinitialise the video mode.
318695b296d0Smrg */
318795b296d0Smrg
318895b296d0Smrg/* Mandatory */
318995b296d0Smrgstatic Bool
319095b296d0SmrgTRIDENTEnterVT(int scrnIndex, int flags)
319195b296d0Smrg{
319295b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
319395b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
319495b296d0Smrg
319595b296d0Smrg    if (IsPciCard && UseMMIO) TRIDENTEnableMMIO(pScrn);
319695b296d0Smrg
319795b296d0Smrg    /* Should we re-save the text mode on each VT enter? */
319895b296d0Smrg    if (!TRIDENTModeInit(pScrn, pScrn->currentMode))
319995b296d0Smrg	return FALSE;
320095b296d0Smrg
320195b296d0Smrg    if (pTrident->InitializeAccelerator)
320295b296d0Smrg        pTrident->InitializeAccelerator(pScrn);
320395b296d0Smrg
320495b296d0Smrg    return TRUE;
320595b296d0Smrg}
320695b296d0Smrg
320795b296d0Smrg
320895b296d0Smrg/*
320995b296d0Smrg * This is called when VT switching away from the X server.  Its job is
321095b296d0Smrg * to restore the previous (text) mode.
321195b296d0Smrg *
321295b296d0Smrg * We may wish to remap video/MMIO memory too.
321395b296d0Smrg */
321495b296d0Smrg
321595b296d0Smrg/* Mandatory */
321695b296d0Smrgstatic void
321795b296d0SmrgTRIDENTLeaveVT(int scrnIndex, int flags)
321895b296d0Smrg{
321995b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
322095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
322195b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
322295b296d0Smrg
322395b296d0Smrg    if (!pTrident->NoAccel && !pTrident->useEXA)
322495b296d0Smrg	pTrident->AccelInfoRec->Sync(pScrn);
322595b296d0Smrg    else if (!pTrident->NoAccel && pTrident->useEXA)
322695b296d0Smrg	pTrident->EXADriverPtr->WaitMarker(pScrn->pScreen, 0);
322795b296d0Smrg
322895b296d0Smrg    TRIDENTRestore(pScrn);
322995b296d0Smrg    vgaHWLock(hwp);
323095b296d0Smrg
323195b296d0Smrg    if (xf86IsPc98())
323295b296d0Smrg	PC98TRIDENTDisable(pScrn);
323395b296d0Smrg
323495b296d0Smrg    if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn);
323595b296d0Smrg}
323695b296d0Smrg
323795b296d0Smrg
323895b296d0Smrg/*
323995b296d0Smrg * This is called at the end of each server generation.  It restores the
324095b296d0Smrg * original (text) mode.  It should really also unmap the video memory too.
324195b296d0Smrg */
324295b296d0Smrg
324395b296d0Smrg/* Mandatory */
324495b296d0Smrgstatic Bool
324595b296d0SmrgTRIDENTCloseScreen(int scrnIndex, ScreenPtr pScreen)
324695b296d0Smrg{
324795b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
324895b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
324995b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
325095b296d0Smrg
325195b296d0Smrg    if (pScrn->vtSema) {
325295b296d0Smrg    if (!pTrident->NoAccel && !pTrident->useEXA)
325395b296d0Smrg	pTrident->AccelInfoRec->Sync(pScrn);
325495b296d0Smrg    else if (!pTrident->NoAccel && pTrident->useEXA)
325595b296d0Smrg	pTrident->EXADriverPtr->WaitMarker(pScreen, 0);
325695b296d0Smrg
325795b296d0Smrg    if (xf86IsPc98())
325895b296d0Smrg	PC98TRIDENTDisable(pScrn);
325995b296d0Smrg
326095b296d0Smrg    	TRIDENTRestore(pScrn);
326195b296d0Smrg    	vgaHWLock(hwp);
326295b296d0Smrg	if (IsPciCard && UseMMIO) TRIDENTDisableMMIO(pScrn);
326395b296d0Smrg    	TRIDENTUnmapMem(pScrn);
326495b296d0Smrg    }
326595b296d0Smrg    if (pTrident->AccelInfoRec)
326695b296d0Smrg	XAADestroyInfoRec(pTrident->AccelInfoRec);
326795b296d0Smrg    if (pTrident->EXADriverPtr) {
326895b296d0Smrg	exaDriverFini(pScreen);
326995b296d0Smrg	xfree(pTrident->EXADriverPtr);
327095b296d0Smrg	pTrident->EXADriverPtr = NULL;
327195b296d0Smrg    }
327295b296d0Smrg    if (pTrident->CursorInfoRec)
327395b296d0Smrg	xf86DestroyCursorInfoRec(pTrident->CursorInfoRec);
327495b296d0Smrg    if (pTrident->ShadowPtr)
327595b296d0Smrg	xfree(pTrident->ShadowPtr);
327695b296d0Smrg    if (pTrident->DGAModes)
327795b296d0Smrg	xfree(pTrident->DGAModes);
327895b296d0Smrg    pScrn->vtSema = FALSE;
327995b296d0Smrg
328095b296d0Smrg    if(pTrident->BlockHandler)
328195b296d0Smrg	pScreen->BlockHandler = pTrident->BlockHandler;
328295b296d0Smrg
328395b296d0Smrg    if (pTrident->pVbe)
328495b296d0Smrg	vbeFree(pTrident->pVbe);
328595b296d0Smrg    else
328695b296d0Smrg	xf86FreeInt10(pTrident->Int10);
328795b296d0Smrg    pScreen->CloseScreen = pTrident->CloseScreen;
328895b296d0Smrg    return (*pScreen->CloseScreen)(scrnIndex, pScreen);
328995b296d0Smrg}
329095b296d0Smrg
329195b296d0Smrg
329295b296d0Smrg/* Free up any per-generation data structures */
329395b296d0Smrg
329495b296d0Smrg/* Optional */
329595b296d0Smrgstatic void
329695b296d0SmrgTRIDENTFreeScreen(int scrnIndex, int flags)
329795b296d0Smrg{
329895b296d0Smrg    if (xf86LoaderCheckSymbol("vgaHWFreeHWRec"))
329995b296d0Smrg	vgaHWFreeHWRec(xf86Screens[scrnIndex]);
330095b296d0Smrg    TRIDENTFreeRec(xf86Screens[scrnIndex]);
330195b296d0Smrg}
330295b296d0Smrg
330395b296d0Smrg
330495b296d0Smrg/* Checks if a mode is suitable for the selected chipset. */
330595b296d0Smrg
330695b296d0Smrg/* Optional */
330795b296d0Smrgstatic ModeStatus
330895b296d0SmrgTRIDENTValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
330995b296d0Smrg{
331095b296d0Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
331195b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
331295b296d0Smrg
331395b296d0Smrg    if (pTrident->lcdActive && (pTrident->lcdMode != 0xff)){
331495b296d0Smrg	if (((mode->HDisplay > LCD[pTrident->lcdMode].display_x)
331595b296d0Smrg	|| (mode->VDisplay > LCD[pTrident->lcdMode].display_y))) {
331695b296d0Smrg	    xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) "
331795b296d0Smrg		       "larger than the LCD panel (%dx%d)\n",
331895b296d0Smrg		       mode->HDisplay,
331995b296d0Smrg		       mode->VDisplay,
332095b296d0Smrg		       LCD[pTrident->lcdMode].display_x,
332195b296d0Smrg		       LCD[pTrident->lcdMode].display_y);
332295b296d0Smrg	    return(MODE_BAD);
332395b296d0Smrg	}
332495b296d0Smrg	if (((float)mode->HDisplay/(float)mode->VDisplay) > 2.0) {
332595b296d0Smrg	    xf86DrvMsg(scrnIndex,X_INFO, "Removing mode (%dx%d) "
332695b296d0Smrg		       "unusual aspect ratio\n",
332795b296d0Smrg		       mode->HDisplay,
332895b296d0Smrg		       mode->VDisplay);
332995b296d0Smrg	    return(MODE_BAD);
333095b296d0Smrg	}
333195b296d0Smrg    }
333295b296d0Smrg    return (MODE_OK);
333395b296d0Smrg}
333495b296d0Smrg
333595b296d0Smrg/* Do screen blanking */
333695b296d0Smrg
333795b296d0Smrg/* Mandatory */
333895b296d0Smrgstatic Bool
333995b296d0SmrgTRIDENTSaveScreen(ScreenPtr pScreen, int mode)
334095b296d0Smrg{
334195b296d0Smrg    return vgaHWSaveScreen(pScreen, mode);
334295b296d0Smrg}
334395b296d0Smrg
334495b296d0Smrgstatic void
334595b296d0SmrgTRIDENTEnableMMIO(ScrnInfoPtr pScrn)
334695b296d0Smrg{
334795b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
334895b296d0Smrg    IOADDRESS vgaIOBase = pTrident->PIOBase + VGAHWPTR(pScrn)->IOBase;
334995b296d0Smrg    CARD8 temp = 0, protect = 0;
335095b296d0Smrg
335195b296d0Smrg    /*
335295b296d0Smrg     * Skip MMIO Enable in PC-9821 PCI Trident Card!!
335395b296d0Smrg     * Because of lack of non PCI VGA port
335495b296d0Smrg     */
335595b296d0Smrg    if (IsPciCard && xf86IsPc98())
335695b296d0Smrg      return;
335795b296d0Smrg
335895b296d0Smrg    /* Goto New Mode */
335995b296d0Smrg    outb(pTrident->PIOBase + 0x3C4, 0x0B);
336095b296d0Smrg    inb(pTrident->PIOBase + 0x3C5);
336195b296d0Smrg
336295b296d0Smrg    /* Unprotect registers */
336395b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
336495b296d0Smrg    	outb(pTrident->PIOBase + 0x3C4, Protection);
336595b296d0Smrg    	protect = inb(pTrident->PIOBase + 0x3C5);
336695b296d0Smrg    	outb(pTrident->PIOBase + 0x3C5, 0x92);
336795b296d0Smrg    }
336895b296d0Smrg    outb(pTrident->PIOBase + 0x3C4, NewMode1);
336995b296d0Smrg    temp = inb(pTrident->PIOBase + 0x3C5);
337095b296d0Smrg    outb(pTrident->PIOBase + 0x3C5, 0x80);
337195b296d0Smrg
337295b296d0Smrg    /* Enable MMIO */
337395b296d0Smrg    outb(vgaIOBase + 4, PCIReg);
337495b296d0Smrg    pTrident->REGPCIReg = inb(vgaIOBase + 5);
337595b296d0Smrg    outb(vgaIOBase + 5, pTrident->REGPCIReg | 0x01); /* Enable it */
337695b296d0Smrg
337795b296d0Smrg    /* Protect registers */
337895b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
337995b296d0Smrg    	OUTB(0x3C4, Protection);
338095b296d0Smrg    	OUTB(0x3C5, protect);
338195b296d0Smrg    }
338295b296d0Smrg    OUTB(0x3C4, NewMode1);
338395b296d0Smrg    OUTB(0x3C5, temp);
338495b296d0Smrg}
338595b296d0Smrg
338695b296d0Smrgstatic void
338795b296d0SmrgTRIDENTDisableMMIO(ScrnInfoPtr pScrn)
338895b296d0Smrg{
338995b296d0Smrg    int vgaIOBase = VGAHWPTR(pScrn)->IOBase;
339095b296d0Smrg    CARD8 temp = 0, protect = 0;
339195b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
339295b296d0Smrg
339395b296d0Smrg    /*
339495b296d0Smrg     * Skip MMIO Disable in PC-9821 PCI Trident Card!!
339595b296d0Smrg     * Because of lack of non PCI VGA port
339695b296d0Smrg     */
339795b296d0Smrg    if (IsPciCard && xf86IsPc98())
339895b296d0Smrg      return;
339995b296d0Smrg
340095b296d0Smrg    /* Goto New Mode */
340195b296d0Smrg    OUTB(0x3C4, 0x0B); temp = INB(0x3C5);
340295b296d0Smrg
340395b296d0Smrg    /* Unprotect registers */
340495b296d0Smrg    OUTB(0x3C4, NewMode1); temp = INB(0x3C5);
340595b296d0Smrg    OUTB(0x3C5, 0x80);
340695b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
340795b296d0Smrg    	OUTB(0x3C4, Protection);
340895b296d0Smrg    	protect = INB(0x3C5);
340995b296d0Smrg    	OUTB(0x3C5, 0x92);
341095b296d0Smrg    }
341195b296d0Smrg
341295b296d0Smrg    /* Disable MMIO access */
341395b296d0Smrg    OUTB(vgaIOBase + 4, PCIReg);
341495b296d0Smrg    pTrident->REGPCIReg = INB(vgaIOBase + 5);
341595b296d0Smrg    OUTB(vgaIOBase + 5, pTrident->REGPCIReg & 0xFE);
341695b296d0Smrg
341795b296d0Smrg    /* Protect registers */
341895b296d0Smrg    if (pTrident->Chipset > PROVIDIA9685) {
341995b296d0Smrg    	outb(pTrident->PIOBase + 0x3C4, Protection);
342095b296d0Smrg    	outb(pTrident->PIOBase + 0x3C5, protect);
342195b296d0Smrg    }
342295b296d0Smrg    outb(pTrident->PIOBase + 0x3C4, NewMode1);
342395b296d0Smrg    outb(pTrident->PIOBase + 0x3C5, temp);
342495b296d0Smrg}
342595b296d0Smrg
342695b296d0Smrg/* Initialize VGA Block for Trident Chip on PC-98x1 */
342795b296d0Smrgstatic void
342895b296d0SmrgPC98TRIDENTInit(ScrnInfoPtr pScrn)
342995b296d0Smrg{
343095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
343195b296d0Smrg    switch (pTrident->Chipset) {
343295b296d0Smrg    case TGUI9660:
343395b296d0Smrg    case TGUI9680:
343495b296d0Smrg    case PROVIDIA9682:
343595b296d0Smrg	PC98TRIDENT96xxInit(pScrn);
343695b296d0Smrg	break;
343795b296d0Smrg    case CYBER9320:
343895b296d0Smrg    case CYBER9385:
343995b296d0Smrg	PC98TRIDENT9385Init(pScrn);
344095b296d0Smrg	break;
344195b296d0Smrg    default: /* Run 96xx code as default */
344295b296d0Smrg	PC98TRIDENT96xxInit(pScrn);
344395b296d0Smrg	break;
344495b296d0Smrg    }
344595b296d0Smrg}
344695b296d0Smrg
344795b296d0Smrgstatic void
344895b296d0SmrgPC98TRIDENTEnable(ScrnInfoPtr pScrn)
344995b296d0Smrg{
345095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
345195b296d0Smrg    switch (pTrident->Chipset) {
345295b296d0Smrg    case TGUI9660:
345395b296d0Smrg    case TGUI9680:
345495b296d0Smrg    case PROVIDIA9682:
345595b296d0Smrg	PC98TRIDENT96xxEnable(pScrn);
345695b296d0Smrg	break;
345795b296d0Smrg    case CYBER9320:
345895b296d0Smrg    case CYBER9385:
345995b296d0Smrg	PC98TRIDENT9385Enable(pScrn);
346095b296d0Smrg	break;
346195b296d0Smrg    default: /* Run 96xx code as default */
346295b296d0Smrg	PC98TRIDENT96xxEnable(pScrn);
346395b296d0Smrg	break;
346495b296d0Smrg    }
346595b296d0Smrg}
346695b296d0Smrg
346795b296d0Smrgstatic void
346895b296d0SmrgPC98TRIDENTDisable(ScrnInfoPtr pScrn)
346995b296d0Smrg{
347095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
347195b296d0Smrg    switch (pTrident->Chipset) {
347295b296d0Smrg    case TGUI9660:
347395b296d0Smrg    case TGUI9680:
347495b296d0Smrg    case PROVIDIA9682:
347595b296d0Smrg	PC98TRIDENT96xxDisable(pScrn);
347695b296d0Smrg	break;
347795b296d0Smrg    case CYBER9320:
347895b296d0Smrg    case CYBER9385:
347995b296d0Smrg	PC98TRIDENT9385Disable(pScrn);
348095b296d0Smrg	break;
348195b296d0Smrg    default: /* Run 96xx code as default */
348295b296d0Smrg	PC98TRIDENT96xxDisable(pScrn);
348395b296d0Smrg	break;
348495b296d0Smrg    }
348595b296d0Smrg}
348695b296d0Smrg
348795b296d0Smrg/* Initialize VGA Block for Cyber9385 on PC-98x1 */
348895b296d0Smrgstatic void
348995b296d0SmrgPC98TRIDENT9385Init(ScrnInfoPtr pScrn)
349095b296d0Smrg{
349195b296d0Smrg/* Nothing to initialize */
349295b296d0Smrg}
349395b296d0Smrg
349495b296d0Smrgstatic void
349595b296d0SmrgPC98TRIDENT9385Enable(ScrnInfoPtr pScrn)
349695b296d0Smrg{
349795b296d0Smrg    outb(0xFAC, 0x02);
349895b296d0Smrg}
349995b296d0Smrg
350095b296d0Smrgstatic void
350195b296d0SmrgPC98TRIDENT9385Disable(ScrnInfoPtr pScrn)
350295b296d0Smrg{
350395b296d0Smrg    outb(0xFAC, 0x00);
350495b296d0Smrg}
350595b296d0Smrg
350695b296d0Smrg/* Initialize VGA Block for Trident96xx on PC-98x1 */
350795b296d0Smrgstatic void
350895b296d0SmrgPC98TRIDENT96xxInit(ScrnInfoPtr pScrn)
350995b296d0Smrg{
351095b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
351195b296d0Smrg    vgaHWPtr hwp = VGAHWPTR(pScrn);
351295b296d0Smrg    CARD8 temp = 0;
351395b296d0Smrg
351495b296d0Smrg    vgaHWProtect(pScrn, TRUE);
351595b296d0Smrg
351695b296d0Smrg    /* Video SusSystem Enable */
351795b296d0Smrg    temp = INB(0x3CC);
351895b296d0Smrg    OUTB(0x3C2, temp | 0xC3);
351995b296d0Smrg    /* Switch Old */
352095b296d0Smrg    OUTB(0x3C4, 0x0B); temp = INB(0x3C5);
352195b296d0Smrg    OUTW(0x3C4, 0x0B | (temp << 8));
352295b296d0Smrg    /* Select Configuration Port 1 */
352395b296d0Smrg    OUTB(0x3C4, 0x0E); temp = INB(0x3C5);
352495b296d0Smrg    OUTW(0x3C4, 0x0E | ((temp | 0x20) << 8));
352595b296d0Smrg
352695b296d0Smrg    OUTB(0x3C4, 0x0c);
352795b296d0Smrg    if((INB(0x3C5) & 0x10) == 0x10)
352895b296d0Smrg    {
352995b296d0Smrg	OUTB(0x3C4, 0x0E | (temp << 8));
353095b296d0Smrg	OUTB(0x94,  0x00);
353195b296d0Smrg	OUTB(0x102, 0x01);
353295b296d0Smrg	OUTB(0x94,  0x20);
353395b296d0Smrg	temp = INB(0x3C3);
353495b296d0Smrg	OUTB(0x3C3, temp | 0x01);
353595b296d0Smrg    } else {
353695b296d0Smrg	OUTB(0x3C4, 0x0E | (temp << 8));
353795b296d0Smrg	OUTB(0x46E8, 0x10);
353895b296d0Smrg	OUTB(0x102,  0x01);
353995b296d0Smrg	OUTB(0x46E8, 0x08);
354095b296d0Smrg    }
354195b296d0Smrg
354295b296d0Smrg    INB(0x3DA);
354395b296d0Smrg    OUTB(0x3C0,0x10);
354495b296d0Smrg    OUTB(0x3C0,0x41);
354595b296d0Smrg
354695b296d0Smrg    /* Register Unlock */
354795b296d0Smrg    vgaHWUnlock(hwp);
354895b296d0Smrg    OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Switch New */
354995b296d0Smrg    OUTB(0x3C4, 0x0E); temp = INB(0x3C5);
355095b296d0Smrg    OUTW(0x3C4, 0x0E | ((temp | 0x80) << 8));
355195b296d0Smrg
355295b296d0Smrg    /* For Speed Up [Facoor 2 at Xengine] */
355395b296d0Smrg    OUTW(0x3D4, 0x3820); /* Command FIFO Register */
355495b296d0Smrg    OUTW(0x3D4, 0x2020); /* Command FIFO Register */
355595b296d0Smrg    /* Latency Control Registers 0x30 - 0x32 */
355695b296d0Smrg    /* Parameter Range 0x00 - 0x0F */
355795b296d0Smrg    /* Tune these parameter to avoid GE Timeout */
355895b296d0Smrg    OUTW(0x3D4, 0x0E30); /* Display Queue Latency Control */
355995b296d0Smrg    /* 8bpp GE No Timeout Parameter 0x0D - 0x0F for PC-9821Xa7 TGUi9680 */
356095b296d0Smrg    OUTW(0x3D4, 0x0031); /* Frame Buffer Latency Control */
356195b296d0Smrg    OUTW(0x3D4, 0x0032); /* Display & Frame Buffer Latency Control */
356295b296d0Smrg    OUTW(0x3D4, 0x213B); /* Clock and Tuning */
356395b296d0Smrg
356495b296d0Smrg    /* MCLK Init */
356595b296d0Smrg    OUTB(0x43C6, 0xAF); OUTB(0x43C7, 0x00); /* 80.0MHz */
356695b296d0Smrg#if 0
356795b296d0Smrg    /* Sample MCLKs */
356895b296d0Smrg    OUTB(0x43C6, 0xAF); OUTB(0x43C7, 0x00); /* 80.0MHz */
356995b296d0Smrg    OUTB(0x43C6, 0xA7); OUTB(0x43C7, 0x00); /* 77.0MHz */
357095b296d0Smrg    OUTB(0x43C6, 0x8E); OUTB(0x43C7, 0x00); /* 75.0MHz */
357195b296d0Smrg    OUTB(0x43C6, 0x86); OUTB(0x43C7, 0x00); /* 72.0MHz */
357295b296d0Smrg    OUTB(0x43C6, 0x8F); OUTB(0x43C7, 0x00); /* 67.2MHz */
357395b296d0Smrg    OUTB(0x43C6, 0xD5); OUTB(0x43C7, 0x02); /* 61.6MHz */
357495b296d0Smrg#endif
357595b296d0Smrg
357695b296d0Smrg    /* Register Lock */
357795b296d0Smrg    OUTB(0x3C4, 0x0B); temp = INB(0x3C5); /* Switch New */
357895b296d0Smrg    OUTB(0x3C4, 0x0E); temp = INB(0x3C5);
357995b296d0Smrg    OUTW(0x3C4, 0x0E | ((temp & 0x7F) << 8));
358095b296d0Smrg    vgaHWLock(hwp);
358195b296d0Smrg
358295b296d0Smrg    vgaHWProtect(pScrn, FALSE);
358395b296d0Smrg}
358495b296d0Smrg
358595b296d0Smrgstatic void
358695b296d0SmrgPC98TRIDENT96xxEnable(ScrnInfoPtr pScrn)
358795b296d0Smrg{
358895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
358995b296d0Smrg    CARD8 temp = 0;
359095b296d0Smrg
359195b296d0Smrg    outb(0x68, 0x0E);
359295b296d0Smrg    outb(0x6A, 0x07);
359395b296d0Smrg    outb(0x6A, 0x8F);
359495b296d0Smrg    outb(0x6A, 0x06);
359595b296d0Smrg
359695b296d0Smrg    vgaHWProtect(pScrn, TRUE);
359795b296d0Smrg
359895b296d0Smrg    OUTB(0x3D4, 0x23); temp = INB(0x3D5);
359995b296d0Smrg    OUTW(0x3D4, 0x23 | ((temp & 0xDF) << 8));
360095b296d0Smrg
360195b296d0Smrg    OUTB(0x3D4, 0x29); temp = INB(0x3D5);
360295b296d0Smrg    OUTW(0x3D4, 0x29 | ((temp | 0x04) << 8));
360395b296d0Smrg
360495b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
360595b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x06));
360695b296d0Smrg
360795b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
360895b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x08));
360995b296d0Smrg
361095b296d0Smrg    OUTB(0x3CE, 0x23); temp = INB(0x3CF);
361195b296d0Smrg    OUTW(0x3CE, 0x23 | ((temp & 0xFC) << 8));
361295b296d0Smrg
361395b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
361495b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp | 0x01));
361595b296d0Smrg
361695b296d0Smrg    OUTB(0x3C4, 0x01); temp = INB(0x3C5);
361795b296d0Smrg    OUTW(0x3C4, 0x01 | ((temp & 0xEF) << 8));
361895b296d0Smrg
361995b296d0Smrg    vgaHWProtect(pScrn, FALSE);
362095b296d0Smrg
362195b296d0Smrg    outb(0xFAC, 0x02);
362295b296d0Smrg}
362395b296d0Smrg
362495b296d0Smrgstatic void
362595b296d0SmrgPC98TRIDENT96xxDisable(ScrnInfoPtr pScrn)
362695b296d0Smrg{
362795b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
362895b296d0Smrg    CARD8 temp = 0;
362995b296d0Smrg
363095b296d0Smrg    outb(0xFAC, 0x00);
363195b296d0Smrg
363295b296d0Smrg    vgaHWProtect(pScrn, TRUE);
363395b296d0Smrg
363495b296d0Smrg    OUTB(0x3C4, 0x01); temp = INB(0x3C5);
363595b296d0Smrg    OUTW(0x3C4, 0x01 | ((temp | 0x10) << 8));
363695b296d0Smrg
363795b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
363895b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFE));
363995b296d0Smrg
364095b296d0Smrg    OUTB(0x3CE, 0x23); temp = INB(0x3CF);
364195b296d0Smrg    OUTW(0x3CE, 0x23 | (((temp & 0xFC) | 0x01) << 8));
364295b296d0Smrg
364395b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
364495b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFD));
364595b296d0Smrg
364695b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
364795b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xCF));
364895b296d0Smrg
364995b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
365095b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xF7));
365195b296d0Smrg
365295b296d0Smrg    OUTB(0x83C8, 0x04); temp = INB(0x83c6);
365395b296d0Smrg    OUTB(0x83C8, 0x04); OUTB(0x83c6, (temp & 0xFB));
365495b296d0Smrg
365595b296d0Smrg    OUTB(0x3D4, 0x29); temp = INB(0x3D5);
365695b296d0Smrg    OUTW(0x3D4, 0x29 | ((temp & 0xFB) << 8));
365795b296d0Smrg
365895b296d0Smrg    OUTB(0x3D4, 0x23); temp = INB(0x3D5);
365995b296d0Smrg    OUTW(0x3D4, 0x23 | ((temp | 0x20) << 8));
366095b296d0Smrg
366195b296d0Smrg    vgaHWProtect(pScrn, FALSE);
366295b296d0Smrg
366395b296d0Smrg    outb(0x6A, 0x07);
366495b296d0Smrg    outb(0x6A, 0x8E);
366595b296d0Smrg    outb(0x6A, 0x06);
366695b296d0Smrg    outb(0x68, 0x0F);
366795b296d0Smrg}
366895b296d0Smrg
366995b296d0Smrg
367095b296d0Smrg/*
367195b296d0Smrg * This is a terrible hack! If we are on a notebook in a stretched
367295b296d0Smrg * mode and don't want full screen we use the BIOS to set an unstreched
367395b296d0Smrg * mode.
367495b296d0Smrg */
367595b296d0Smrgvoid
367695b296d0SmrgtridentSetModeBIOS(ScrnInfoPtr pScrn, DisplayModePtr mode)
367795b296d0Smrg{
367895b296d0Smrg    TRIDENTPtr pTrident = TRIDENTPTR(pScrn);
367995b296d0Smrg
368095b296d0Smrg
368195b296d0Smrg#ifdef VBE_INFO
368295b296d0Smrg    if (pTrident->vbeModes) {
368395b296d0Smrg	vbeSaveRestoreRec vbesr;
368495b296d0Smrg	vbesr.stateMode = VBECalcVbeModeIndex(pTrident->vbeModes,
368595b296d0Smrg					     mode, pScrn->bitsPerPixel);
368695b296d0Smrg	vbesr.pstate = NULL;
368795b296d0Smrg	if (vbesr.stateMode) {
368895b296d0Smrg	    if (IsPciCard && UseMMIO)
368995b296d0Smrg		TRIDENTDisableMMIO(pScrn);
369095b296d0Smrg	    VBEVesaSaveRestore(pTrident->pVbe,&vbesr,MODE_RESTORE);
369195b296d0Smrg	    if (IsPciCard && UseMMIO)
369295b296d0Smrg		TRIDENTEnableMMIO(pScrn);
369395b296d0Smrg	    return;
369495b296d0Smrg	} else
369595b296d0Smrg	    xf86DrvMsg(pScrn->scrnIndex,X_WARNING,"No BIOS Mode matches "
369695b296d0Smrg		       "%ix%I@%ibpp\n",mode->HDisplay,mode->VDisplay,
369795b296d0Smrg		       pScrn->bitsPerPixel);
369895b296d0Smrg    }
369995b296d0Smrg#endif
370095b296d0Smrg    /* This function is only for LCD screens, and also when we have
370195b296d0Smrg     * int10 available */
370295b296d0Smrg
370395b296d0Smrg    if (pTrident->IsCyber && pTrident->lcdMode && pTrident->Int10) {
370495b296d0Smrg        int i = pTrident->lcdMode;
370595b296d0Smrg	if ((pScrn->currentMode->HDisplay != LCD[i].display_x) /* !fullsize? */
370695b296d0Smrg	    || (pScrn->currentMode->VDisplay != LCD[i].display_y)) {
370795b296d0Smrg	    if (pTrident->lcdActive)  { /* LCD Active ?*/
370895b296d0Smrg	        int h_str, v_str;
370995b296d0Smrg
371095b296d0Smrg		OUTB(0x3CE,HorStretch);  h_str = INB(0x3CF) & 0x01;
371195b296d0Smrg		OUTB(0x3CE,VertStretch); v_str = INB(0x3CF) & 0x01;
371295b296d0Smrg		if (h_str || v_str) {
371395b296d0Smrg		    OUTB(0x3C4, 0x11); OUTB(0x3C5, 0x92);
371495b296d0Smrg		    OUTW(0x3CE, BiosReg );
371595b296d0Smrg		    pTrident->Int10->ax = 0x3;
371695b296d0Smrg		    pTrident->Int10->num = 0x10;
371795b296d0Smrg		    if (IsPciCard && UseMMIO)
371895b296d0Smrg			TRIDENTDisableMMIO(pScrn);
371995b296d0Smrg		    xf86ExecX86int10(pTrident->Int10);
372095b296d0Smrg		    if (IsPciCard && UseMMIO)
372195b296d0Smrg			TRIDENTEnableMMIO(pScrn);
372295b296d0Smrg		}
372395b296d0Smrg	    }
372495b296d0Smrg	}
372595b296d0Smrg    }
372695b296d0Smrg}
372795b296d0Smrg
372895b296d0Smrg/* Currently we only test for 1400 */
372995b296d0Smrgstatic int
373095b296d0SmrgTRIDENTLcdDisplaySize (xf86MonPtr pMon)
373195b296d0Smrg{
373295b296d0Smrg    if (pMon) {
373395b296d0Smrg	int i,j;
373495b296d0Smrg
373595b296d0Smrg	for (i = 0; i < STD_TIMINGS; i++) {
373695b296d0Smrg	    if (pMon->timings2[i].hsize == 1400) {
373795b296d0Smrg		return 1400;
373895b296d0Smrg	    }
373995b296d0Smrg	}
374095b296d0Smrg	/*
374195b296d0Smrg	 * If not explicitely set try to find out if the display supports
374295b296d0Smrg	 * the 1400 mode. For sanity check if DDC comes from a digital
374395b296d0Smrg	 * display.
374495b296d0Smrg	 */
374595b296d0Smrg	if (DIGITAL(pMon->features.input_type)) {
374695b296d0Smrg	    for (i = 0; i < DET_TIMINGS; i++) {
374795b296d0Smrg		if (pMon->det_mon[i].type == DS_STD_TIMINGS) {
374895b296d0Smrg		    for (j = 0; j < 5; j++) {
374995b296d0Smrg			if (pMon->det_mon[i].section.std_t[j].hsize == 1400) {
375095b296d0Smrg			    return 1400;
375195b296d0Smrg			}
375295b296d0Smrg		    }
375395b296d0Smrg		} else if (pMon->det_mon[i].type == DT) {
375495b296d0Smrg		    if (pMon->det_mon[i].section.d_timings.h_active == 1400) {
375595b296d0Smrg			return 1400;
375695b296d0Smrg		    }
375795b296d0Smrg		}
375895b296d0Smrg	    }
375995b296d0Smrg	}
376095b296d0Smrg    }
376195b296d0Smrg    return 0;
376295b296d0Smrg}
376395b296d0Smrg
3764