smi_driver.c revision 7104f784
109885543Smrg/* Header:   //Mercury/Projects/archives/XFree86/4.0/smi_driver.c-arc   1.42   03 Jan 2001 13:52:16   Frido  $ */
209885543Smrg
309885543Smrg/*
409885543SmrgCopyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
509885543SmrgCopyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
609885543Smrg
709885543SmrgPermission is hereby granted, free of charge, to any person obtaining a copy of
809885543Smrgthis software and associated documentation files (the "Software"), to deal in
909885543Smrgthe Software without restriction, including without limitation the rights to
1009885543Smrguse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
1109885543Smrgof the Software, and to permit persons to whom the Software is furnished to do
1209885543Smrgso, subject to the following conditions:
1309885543Smrg
1409885543SmrgThe above copyright notice and this permission notice shall be included in all
1509885543Smrgcopies or substantial portions of the Software.
1609885543Smrg
1709885543SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1809885543SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
1909885543SmrgNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
2009885543SmrgXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
2109885543SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
2209885543SmrgWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2309885543Smrg
2409885543SmrgExcept as contained in this notice, the names of The XFree86 Project and
2509885543SmrgSilicon Motion shall not be used in advertising or otherwise to promote the
2609885543Smrgsale, use or other dealings in this Software without prior written
2709885543Smrgauthorization from The XFree86 Project or Silicon Motion.
2809885543Smrg*/
2909885543Smrg
3009885543Smrg#ifdef HAVE_CONFIG_H
3109885543Smrg#include "config.h"
3209885543Smrg#endif
3309885543Smrg
3409885543Smrg#include "xf86Resources.h"
3509885543Smrg#include "xf86RAC.h"
3609885543Smrg#include "xf86DDC.h"
3709885543Smrg#include "xf86int10.h"
3809885543Smrg#include "vbe.h"
3909885543Smrg
4009885543Smrg#include "smi.h"
417104f784Smrg#include "smi_501.h"
427104f784Smrg#include "smilynx.h"
437104f784Smrg#include "smi_crtc.h"
4409885543Smrg
4509885543Smrg#include "globals.h"
4609885543Smrg#define DPMS_SERVER
4709885543Smrg#include <X11/extensions/dpms.h>
4809885543Smrg
4909885543Smrg/*
5009885543Smrg * Internals
5109885543Smrg */
527104f784Smrgstatic Bool SMI_MapMmio(ScrnInfoPtr pScrn);
537104f784Smrgstatic Bool SMI_DetectMem(ScrnInfoPtr pScrn);
5409885543Smrgstatic void SMI_EnableMmio(ScrnInfoPtr pScrn);
5509885543Smrgstatic void SMI_DisableMmio(ScrnInfoPtr pScrn);
567104f784Smrgstatic Bool SMI_HWInit(ScrnInfoPtr pScrn);
5709885543Smrg
5809885543Smrg/*
5909885543Smrg * Forward definitions for the functions that make up the driver.
6009885543Smrg */
6109885543Smrg
6209885543Smrgstatic const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid);
6309885543Smrgstatic void SMI_Identify(int flags);
6409885543Smrgstatic Bool SMI_Probe(DriverPtr drv, int flags);
6509885543Smrgstatic Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
6609885543Smrgstatic Bool SMI_EnterVT(int scrnIndex, int flags);
6709885543Smrgstatic void SMI_LeaveVT(int scrnIndex, int flags);
6809885543Smrgstatic Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
6909885543Smrg                           char **argv);
7009885543Smrgstatic void SMI_DisableVideo(ScrnInfoPtr pScrn);
7109885543Smrgstatic void SMI_EnableVideo(ScrnInfoPtr pScrn);
7209885543Smrgstatic Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen);
7309885543Smrgstatic Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
7409885543Smrgstatic void SMI_FreeScreen(int ScrnIndex, int flags);
7509885543Smrgstatic void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
7609885543Smrgstatic void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
777104f784Smrgstatic void SMI_DetectMCLK(ScrnInfoPtr pScrn);
7809885543Smrg
797104f784Smrg/*
807104f784Smrg * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
817104f784Smrg * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion"
827104f784Smrg */
837104f784Smrg#define SILICONMOTION_NAME          "SMI"
8409885543Smrg#define SILICONMOTION_DRIVER_NAME   "siliconmotion"
857104f784Smrg#define SILICONMOTION_VERSION_NAME  PACKAGE_VERSION
867104f784Smrg#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR
877104f784Smrg#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR
887104f784Smrg#define SILICONMOTION_PATCHLEVEL    PACKAGE_VERSION_PATCHLEVEL
8909885543Smrg#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
9009885543Smrg                                      (SILICONMOTION_VERSION_MINOR << 16) | \
9109885543Smrg                                      (SILICONMOTION_PATCHLEVEL))
9209885543Smrg
937104f784Smrg#if SMI_DEBUG
947104f784Smrgint smi_indent = 1;
957104f784Smrg#endif
967104f784Smrg
977104f784Smrg/* for dualhead */
987104f784Smrgint gSMIEntityIndex = -1;
997104f784Smrg
10009885543Smrg/*
10109885543Smrg * This contains the functions needed by the server after loading the
10209885543Smrg * driver module.  It must be supplied, and gets added the driver list by
10309885543Smrg * the Module Setup funtion in the dynamic case.  In the static case a
10409885543Smrg * reference to this is compiled in, and this requires that the name of
10509885543Smrg * this DriverRec be an upper-case version of the driver name.
10609885543Smrg */
10709885543Smrg
10809885543Smrg_X_EXPORT DriverRec SILICONMOTION =
10909885543Smrg{
11009885543Smrg    SILICONMOTION_DRIVER_VERSION,
11109885543Smrg    SILICONMOTION_DRIVER_NAME,
11209885543Smrg    SMI_Identify,
11309885543Smrg    SMI_Probe,
11409885543Smrg    SMI_AvailableOptions,
11509885543Smrg    NULL,
11609885543Smrg    0
11709885543Smrg};
11809885543Smrg
11909885543Smrg/* Supported chipsets */
12009885543Smrgstatic SymTabRec SMIChipsets[] =
12109885543Smrg{
12209885543Smrg    { PCI_CHIP_SMI910, "Lynx"    },
12309885543Smrg    { PCI_CHIP_SMI810, "LynxE"   },
12409885543Smrg    { PCI_CHIP_SMI820, "Lynx3D"  },
12509885543Smrg    { PCI_CHIP_SMI710, "LynxEM"  },
12609885543Smrg    { PCI_CHIP_SMI712, "LynxEM+" },
12709885543Smrg    { PCI_CHIP_SMI720, "Lynx3DM" },
12809885543Smrg    { PCI_CHIP_SMI731, "Cougar3DR" },
1297104f784Smrg    { PCI_CHIP_SMI501, "MSOC"	 },
13009885543Smrg    { -1,             NULL      }
13109885543Smrg};
13209885543Smrg
13309885543Smrgstatic PciChipsets SMIPciChipsets[] =
13409885543Smrg{
1357104f784Smrg    /* numChipset,	PciID,			Resource */
13609885543Smrg    { PCI_CHIP_SMI910,	PCI_CHIP_SMI910,	RES_SHARED_VGA },
13709885543Smrg    { PCI_CHIP_SMI810,	PCI_CHIP_SMI810,	RES_SHARED_VGA },
13809885543Smrg    { PCI_CHIP_SMI820,	PCI_CHIP_SMI820,	RES_SHARED_VGA },
13909885543Smrg    { PCI_CHIP_SMI710,	PCI_CHIP_SMI710,	RES_SHARED_VGA },
14009885543Smrg    { PCI_CHIP_SMI712,	PCI_CHIP_SMI712,	RES_SHARED_VGA },
14109885543Smrg    { PCI_CHIP_SMI720,	PCI_CHIP_SMI720,	RES_SHARED_VGA },
14209885543Smrg    { PCI_CHIP_SMI731,	PCI_CHIP_SMI731,	RES_SHARED_VGA },
1437104f784Smrg    { PCI_CHIP_SMI501,	PCI_CHIP_SMI501,	RES_UNDEFINED  },
1447104f784Smrg    { -1,		-1,			RES_UNDEFINED  }
14509885543Smrg};
14609885543Smrg
14709885543Smrgtypedef enum
14809885543Smrg{
14909885543Smrg    OPTION_PCI_BURST,
15009885543Smrg    OPTION_PCI_RETRY,
15109885543Smrg    OPTION_NOACCEL,
15209885543Smrg    OPTION_MCLK,
1537104f784Smrg    OPTION_MXCLK,
15409885543Smrg    OPTION_SWCURSOR,
15509885543Smrg    OPTION_HWCURSOR,
15609885543Smrg    OPTION_VIDEOKEY,
15709885543Smrg    OPTION_BYTESWAP,
15809885543Smrg    /* CZ 26.10.2001: interlaced video */
15909885543Smrg    OPTION_INTERLACED,
16009885543Smrg    /* end CZ */
16109885543Smrg    OPTION_USEBIOS,
16209885543Smrg    OPTION_DUALHEAD,
16309885543Smrg    OPTION_ACCELMETHOD,
1647104f784Smrg    OPTION_PANEL_SIZE,
1657104f784Smrg    OPTION_USE_FBDEV,
1667104f784Smrg    OPTION_CSCVIDEO,
16709885543Smrg    NUMBER_OF_OPTIONS
16809885543Smrg} SMIOpts;
16909885543Smrg
17009885543Smrgstatic const OptionInfoRec SMIOptions[] =
17109885543Smrg{
1727104f784Smrg    { OPTION_PCI_BURST,	     "pci_burst",	  OPTV_BOOLEAN, {0}, TRUE },
1737104f784Smrg    { OPTION_PCI_RETRY,	     "pci_retry",	  OPTV_BOOLEAN, {0}, TRUE },
17409885543Smrg    { OPTION_NOACCEL,	     "NoAccel",		  OPTV_BOOLEAN, {0}, FALSE },
1757104f784Smrg    { OPTION_MCLK,	     "MCLK",		  OPTV_FREQ,	{0}, FALSE },
1767104f784Smrg    { OPTION_MXCLK,	     "MXCLK",		  OPTV_FREQ,	{0}, FALSE },
1777104f784Smrg    { OPTION_HWCURSOR,	     "HWCursor",	  OPTV_BOOLEAN, {0}, TRUE },
17809885543Smrg    { OPTION_SWCURSOR,	     "SWCursor",	  OPTV_BOOLEAN, {0}, FALSE },
17909885543Smrg    { OPTION_VIDEOKEY,	     "VideoKey",	  OPTV_INTEGER, {0}, FALSE },
18009885543Smrg    { OPTION_BYTESWAP,	     "ByteSwap",	  OPTV_BOOLEAN, {0}, FALSE },
18109885543Smrg    /* CZ 26.10.2001: interlaced video */
1827104f784Smrg    { OPTION_INTERLACED,     "Interlaced",        OPTV_BOOLEAN, {0}, FALSE },
18309885543Smrg    /* end CZ */
18409885543Smrg    { OPTION_USEBIOS,	     "UseBIOS",		  OPTV_BOOLEAN,	{0}, FALSE },
1857104f784Smrg    { OPTION_DUALHEAD,	     "Dualhead",	  OPTV_BOOLEAN,	{0}, TRUE },
18609885543Smrg    { OPTION_ACCELMETHOD,    "AccelMethod",       OPTV_STRING,  {0}, FALSE },
1877104f784Smrg    { OPTION_PANEL_SIZE,     "PanelSize",	  OPTV_ANYSTR,	{0}, FALSE },
1887104f784Smrg    { OPTION_USE_FBDEV,	     "UseFBDev",	  OPTV_BOOLEAN,	{0}, FALSE },
1897104f784Smrg    { OPTION_CSCVIDEO,	     "CSCVideo",	  OPTV_BOOLEAN, {0}, TRUE },
19009885543Smrg    { -1,		     NULL,		  OPTV_NONE,	{0}, FALSE }
19109885543Smrg};
19209885543Smrg
19309885543Smrg/*
19409885543Smrg * Lists of symbols that may/may not be required by this driver.
19509885543Smrg * This allows the loader to know which ones to issue warnings for.
19609885543Smrg *
19709885543Smrg * Note that vgahwSymbols and xaaSymbols are referenced outside the
19809885543Smrg * XFree86LOADER define in later code, so are defined outside of that
19909885543Smrg * define here also.
20009885543Smrg */
20109885543Smrg
20209885543Smrgstatic const char *vgahwSymbols[] =
20309885543Smrg{
20409885543Smrg    "vgaHWCopyReg",
20509885543Smrg    "vgaHWGetHWRec",
20609885543Smrg    "vgaHWGetIOBase",
20709885543Smrg    "vgaHWGetIndex",
20809885543Smrg    "vgaHWInit",
20909885543Smrg    "vgaHWLock",
21009885543Smrg    "vgaHWMapMem",
21109885543Smrg    "vgaHWProtect",
21209885543Smrg    "vgaHWRestore",
21309885543Smrg    "vgaHWSave",
21409885543Smrg    "vgaHWSaveScreen",
21509885543Smrg    "vgaHWSetMmioFuncs",
21609885543Smrg    "vgaHWSetStdFuncs",
21709885543Smrg    "vgaHWUnmapMem",
21809885543Smrg    "vgaHWddc1SetSpeedWeak",
21909885543Smrg    NULL
22009885543Smrg};
22109885543Smrg
22209885543Smrgstatic const char *xaaSymbols[] =
22309885543Smrg{
22409885543Smrg    "XAAGetCopyROP",
22509885543Smrg    "XAACreateInfoRec",
22609885543Smrg    "XAADestroyInfoRec",
22709885543Smrg    "XAAGetFallbackOps",
22809885543Smrg    "XAAInit",
22909885543Smrg    "XAAGetPatternROP",
23009885543Smrg    NULL
23109885543Smrg};
23209885543Smrg
23309885543Smrgstatic const char *exaSymbols[] =
23409885543Smrg{
23509885543Smrg    "exaDriverAlloc",
23609885543Smrg    "exaDriverInit",
23709885543Smrg    "exaDriverFini",
23809885543Smrg    "exaOffscreenAlloc",
23909885543Smrg    "exaOffscreenFree",
24009885543Smrg    "exaGetPixmapPitch",
24109885543Smrg    "exaGetPixmapOffset",
24209885543Smrg    "exaGetPixmapSize",
24309885543Smrg    NULL
24409885543Smrg};
24509885543Smrg
24609885543Smrgstatic const char *ddcSymbols[] =
24709885543Smrg{
24809885543Smrg    "xf86PrintEDID",
24909885543Smrg    "xf86DoEDID_DDC1",
25009885543Smrg    "xf86DoEDID_DDC2",
25109885543Smrg    "xf86SetDDCproperties",
25209885543Smrg    NULL
25309885543Smrg};
25409885543Smrg
25509885543Smrgstatic const char *i2cSymbols[] =
25609885543Smrg{
25709885543Smrg    "xf86CreateI2CBusRec",
25809885543Smrg    "xf86CreateI2CDevRec",
25909885543Smrg    "xf86DestroyI2CBusRec",
26009885543Smrg    "xf86DestroyI2CDevRec",
26109885543Smrg    "xf86I2CBusInit",
26209885543Smrg    "xf86I2CDevInit",
26309885543Smrg    "xf86I2CReadBytes",
26409885543Smrg    "xf86I2CWriteByte",
26509885543Smrg    NULL
26609885543Smrg};
26709885543Smrg
26809885543Smrgstatic const char *int10Symbols[] =
26909885543Smrg{
27009885543Smrg    "xf86ExecX86int10",
27109885543Smrg    "xf86FreeInt10",
27209885543Smrg    "xf86InitInt10",
27309885543Smrg    NULL
27409885543Smrg};
27509885543Smrg
27609885543Smrgstatic const char *vbeSymbols[] =
27709885543Smrg{
27809885543Smrg    "VBEInit",
27909885543Smrg    "vbeDoEDID",
28009885543Smrg    "vbeFree",
28109885543Smrg    NULL
28209885543Smrg};
28309885543Smrg
28409885543Smrgstatic const char *fbSymbols[] =
28509885543Smrg{
28609885543Smrg    "fbPictureInit",
28709885543Smrg    "fbScreenInit",
28809885543Smrg    NULL
28909885543Smrg};
29009885543Smrg
29109885543Smrg#ifdef XFree86LOADER
29209885543Smrg
29309885543Smrgstatic MODULESETUPPROTO(siliconmotionSetup);
29409885543Smrg
29509885543Smrgstatic XF86ModuleVersionInfo SMIVersRec =
29609885543Smrg{
29709885543Smrg    "siliconmotion",
29809885543Smrg    MODULEVENDORSTRING,
29909885543Smrg    MODINFOSTRING1,
30009885543Smrg    MODINFOSTRING2,
30109885543Smrg    XORG_VERSION_CURRENT,
30209885543Smrg    SILICONMOTION_VERSION_MAJOR,
30309885543Smrg    SILICONMOTION_VERSION_MINOR,
30409885543Smrg    SILICONMOTION_PATCHLEVEL,
30509885543Smrg    ABI_CLASS_VIDEODRV,
30609885543Smrg    ABI_VIDEODRV_VERSION,
30709885543Smrg    MOD_CLASS_VIDEODRV,
30809885543Smrg    {0, 0, 0, 0}
30909885543Smrg};
31009885543Smrg
31109885543Smrg/*
31209885543Smrg * This is the module init data for XFree86 modules.
31309885543Smrg *
31409885543Smrg * Its name has to be the driver name followed by ModuleData.
31509885543Smrg */
31609885543Smrg_X_EXPORT XF86ModuleData siliconmotionModuleData =
31709885543Smrg{
31809885543Smrg    &SMIVersRec,
31909885543Smrg    siliconmotionSetup,
32009885543Smrg    NULL
32109885543Smrg};
32209885543Smrg
32309885543Smrgstatic pointer
32409885543SmrgsiliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin)
32509885543Smrg{
32609885543Smrg    static Bool setupDone = FALSE;
32709885543Smrg
32809885543Smrg    if (!setupDone) {
32909885543Smrg	setupDone = TRUE;
33009885543Smrg	xf86AddDriver(&SILICONMOTION, module, 0);
33109885543Smrg
33209885543Smrg	/*
33309885543Smrg	 * Modules that this driver always requires can be loaded here
33409885543Smrg	 * by calling LoadSubModule().
33509885543Smrg	 */
33609885543Smrg
33709885543Smrg	/*
33809885543Smrg	 * Tell the loader about symbols from other modules that this module
33909885543Smrg	 * might refer to.
34009885543Smrg	 */
3417104f784Smrg	LoaderRefSymLists(vgahwSymbols, fbSymbols, xaaSymbols, exaSymbols,
34209885543Smrg					  ddcSymbols, i2cSymbols, int10Symbols, vbeSymbols,
3437104f784Smrg					  NULL);
34409885543Smrg
34509885543Smrg	/*
34609885543Smrg	 * The return value must be non-NULL on success even though there
34709885543Smrg	 * is no TearDownProc.
34809885543Smrg	 */
34909885543Smrg	return (pointer) 1;
35009885543Smrg
35109885543Smrg    } else {
35209885543Smrg	if (errmaj) {
35309885543Smrg	    *errmaj = LDR_ONCEONLY;
35409885543Smrg	}
35509885543Smrg	return NULL;
35609885543Smrg    }
35709885543Smrg}
35809885543Smrg
35909885543Smrg#endif /* XFree86LOADER */
36009885543Smrg
36109885543Smrgstatic Bool
36209885543SmrgSMI_GetRec(ScrnInfoPtr pScrn)
36309885543Smrg{
3647104f784Smrg    ENTER();
36509885543Smrg
36609885543Smrg    /*
36709885543Smrg     * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
36809885543Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
36909885543Smrg     * the allocation has already been done.
37009885543Smrg     */
37109885543Smrg    if (pScrn->driverPrivate == NULL) {
37209885543Smrg	pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
37309885543Smrg    }
37409885543Smrg
3757104f784Smrg    LEAVE(TRUE);
37609885543Smrg}
37709885543Smrg
37809885543Smrgstatic void
37909885543SmrgSMI_FreeRec(ScrnInfoPtr pScrn)
38009885543Smrg{
3817104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
38209885543Smrg
3837104f784Smrg    ENTER();
3847104f784Smrg
3857104f784Smrg    if (pSmi) {
3867104f784Smrg	xfree(pSmi->save);
3877104f784Smrg	xfree(pSmi->mode);
38809885543Smrg	xfree(pScrn->driverPrivate);
38909885543Smrg	pScrn->driverPrivate = NULL;
39009885543Smrg    }
39109885543Smrg
3927104f784Smrg    LEAVE();
39309885543Smrg}
39409885543Smrg
39509885543Smrgstatic const OptionInfoRec *
39609885543SmrgSMI_AvailableOptions(int chipid, int busid)
39709885543Smrg{
3987104f784Smrg    ENTER();
3997104f784Smrg
4007104f784Smrg    LEAVE(SMIOptions);
40109885543Smrg}
40209885543Smrg
40309885543Smrgstatic void
40409885543SmrgSMI_Identify(int flags)
40509885543Smrg{
4067104f784Smrg    ENTER();
40709885543Smrg
40809885543Smrg    xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
40909885543Smrg		SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
41009885543Smrg		SMIChipsets);
41109885543Smrg
4127104f784Smrg    LEAVE();
41309885543Smrg}
41409885543Smrg
41509885543Smrgstatic Bool
41609885543SmrgSMI_Probe(DriverPtr drv, int flags)
41709885543Smrg{
41809885543Smrg    int i;
41909885543Smrg    GDevPtr *devSections;
42009885543Smrg    int *usedChips;
42109885543Smrg    int numDevSections;
42209885543Smrg    int numUsed;
42309885543Smrg    Bool foundScreen = FALSE;
42409885543Smrg
4257104f784Smrg    ENTER();
42609885543Smrg
42709885543Smrg    numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
42809885543Smrg
4297104f784Smrg    if (numDevSections <= 0)
43009885543Smrg	/* There's no matching device section in the config file, so quit now. */
4317104f784Smrg	LEAVE(FALSE);
43209885543Smrg
4337104f784Smrg#ifndef XSERVER_LIBPCIACCESS
4347104f784Smrg    if (xf86GetPciVideoInfo() == NULL)
4357104f784Smrg	LEAVE(FALSE);
4367104f784Smrg#endif
43709885543Smrg
43809885543Smrg    numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
43909885543Smrg				    SMIChipsets, SMIPciChipsets, devSections,
44009885543Smrg				    numDevSections, drv, &usedChips);
44109885543Smrg
44209885543Smrg    /* Free it since we don't need that list after this */
44309885543Smrg    xfree(devSections);
4447104f784Smrg    if (numUsed <= 0)
4457104f784Smrg	LEAVE(FALSE);
4467104f784Smrg
4477104f784Smrg    if (flags & PROBE_DETECT)
4487104f784Smrg	foundScreen = TRUE;
4497104f784Smrg    else {
4507104f784Smrg	ScrnInfoPtr	pScrn;
4517104f784Smrg	EntityInfoPtr	pEnt;
45209885543Smrg
45309885543Smrg	for (i = 0; i < numUsed; i++) {
4547104f784Smrg	    if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
4557104f784Smrg					     SMIPciChipsets, NULL,
4567104f784Smrg					     NULL, NULL, NULL, NULL))) {
4577104f784Smrg		pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
4587104f784Smrg		pScrn->driverName    = SILICONMOTION_DRIVER_NAME;
4597104f784Smrg		pScrn->name	     = SILICONMOTION_NAME;
4607104f784Smrg		pScrn->Probe	     = SMI_Probe;
4617104f784Smrg		pScrn->PreInit	     = SMI_PreInit;
4627104f784Smrg		pScrn->ScreenInit    = SMI_ScreenInit;
4637104f784Smrg		pScrn->SwitchMode    = SMI_SwitchMode;
4647104f784Smrg		pScrn->AdjustFrame   = SMI_AdjustFrame;
4657104f784Smrg
4667104f784Smrg		if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
4677104f784Smrg			pScrn->EnterVT   = SMI_EnterVT;
4687104f784Smrg			pScrn->LeaveVT   = SMI_LeaveVT;
4697104f784Smrg		    xfree(pEnt);
4707104f784Smrg		}
4717104f784Smrg		pScrn->FreeScreen    = SMI_FreeScreen;
4727104f784Smrg		foundScreen	     = TRUE;
4737104f784Smrg	    }
47409885543Smrg	}
47509885543Smrg    }
47609885543Smrg    xfree(usedChips);
47709885543Smrg
4787104f784Smrg    LEAVE(foundScreen);
47909885543Smrg}
48009885543Smrg
48109885543Smrgstatic Bool
48209885543SmrgSMI_PreInit(ScrnInfoPtr pScrn, int flags)
48309885543Smrg{
48409885543Smrg    EntityInfoPtr pEnt;
48509885543Smrg    SMIPtr pSmi;
48609885543Smrg    MessageType from;
48709885543Smrg    vgaHWPtr hwp;
48809885543Smrg
4897104f784Smrg    ENTER();
49009885543Smrg
49109885543Smrg    /* Ignoring the Type list for now.  It might be needed when multiple cards
49209885543Smrg     * are supported.
49309885543Smrg     */
4947104f784Smrg    if (pScrn->numEntities > 1)
4957104f784Smrg	LEAVE(FALSE);
49609885543Smrg
4977104f784Smrg    /* Allocate the SMIRec driverPrivate */
4987104f784Smrg    if (!SMI_GetRec(pScrn))
4997104f784Smrg	LEAVE(FALSE);
5007104f784Smrg    pSmi = SMIPTR(pScrn);
50109885543Smrg
5027104f784Smrg    /* Find the PCI slot for this screen */
5037104f784Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
50409885543Smrg
5057104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
5067104f784Smrg    pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
5077104f784Smrg
5087104f784Smrg    if (IS_MSOC(pSmi)) {
5097104f784Smrg	pSmi->Save = SMI501_Save;
5107104f784Smrg	pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
5117104f784Smrg	pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
5127104f784Smrg    }
5137104f784Smrg    else {
5147104f784Smrg	pSmi->Save = SMILynx_Save;
5157104f784Smrg	pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
5167104f784Smrg	pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
51709885543Smrg    }
51809885543Smrg
5197104f784Smrg    if (flags & PROBE_DETECT) {
5207104f784Smrg	if (!IS_MSOC(pSmi))
5217104f784Smrg	    SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
5227104f784Smrg	LEAVE(TRUE);
52309885543Smrg    }
5247104f784Smrg
5257104f784Smrg    if (pEnt->location.type != BUS_PCI || pEnt->resources) {
5267104f784Smrg	xfree(pEnt);
5277104f784Smrg	SMI_FreeRec(pScrn);
5287104f784Smrg	LEAVE(FALSE);
5297104f784Smrg    }
5307104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
53109885543Smrg
53209885543Smrg    /* Set pScrn->monitor */
53309885543Smrg    pScrn->monitor = pScrn->confScreen->monitor;
53409885543Smrg
5357104f784Smrg    if (!IS_MSOC(pSmi)) {
5367104f784Smrg	/* The vgahw module should be loaded here when needed */
5377104f784Smrg	if (!xf86LoadSubModule(pScrn, "vgahw"))
5387104f784Smrg	    LEAVE(FALSE);
5397104f784Smrg
5407104f784Smrg	xf86LoaderReqSymLists(vgahwSymbols, NULL);
5417104f784Smrg
5427104f784Smrg	/*
5437104f784Smrg	 * Allocate a vgaHWRec
5447104f784Smrg	 */
5457104f784Smrg	if (!vgaHWGetHWRec(pScrn))
5467104f784Smrg	    LEAVE(FALSE);
5477104f784Smrg
5487104f784Smrg	hwp = VGAHWPTR(pScrn);
5497104f784Smrg	pSmi->PIOBase = hwp->PIOOffset;
5507104f784Smrg
5517104f784Smrg	xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
5527104f784Smrg		       "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET,
5537104f784Smrg		       hwp->IOBase, hwp->MMIOBase);
5547104f784Smrg    }
5557104f784Smrg
55609885543Smrg    /*
55709885543Smrg     * The first thing we should figure out is the depth, bpp, etc.
55809885543Smrg     */
5597104f784Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
5607104f784Smrg	LEAVE(FALSE);
56109885543Smrg
56209885543Smrg    /* Check that the returned depth is one we support */
5637104f784Smrg    if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) {
56409885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
56509885543Smrg		   "Given depth (%d) is not supported by this driver\n",
56609885543Smrg		   pScrn->depth);
5677104f784Smrg	LEAVE(FALSE);
5687104f784Smrg    }
5697104f784Smrg
5707104f784Smrg
5717104f784Smrg    if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
5727104f784Smrg       pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
5737104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
5747104f784Smrg		   "Given bpp (%d) is not supported by this driver\n",
5757104f784Smrg		   pScrn->bitsPerPixel);
5767104f784Smrg	LEAVE(FALSE);
57709885543Smrg    }
57809885543Smrg
57909885543Smrg    xf86PrintDepthBpp(pScrn);
58009885543Smrg
58109885543Smrg    /*
58209885543Smrg     * This must happen after pScrn->display has been set because
58309885543Smrg     * xf86SetWeight references it.
58409885543Smrg     */
58509885543Smrg    if (pScrn->depth > 8) {
58609885543Smrg	/* The defaults are OK for us */
58709885543Smrg	rgb zeros = {0, 0, 0};
5887104f784Smrg#if __BYTE_ORDER == __BIG_ENDIAN
5897104f784Smrg	rgb masks = {0xff00,0xff0000,0xff000000};
5907104f784Smrg#else
5917104f784Smrg	rgb masks = {0, 0, 0};
5927104f784Smrg#endif
59309885543Smrg
5947104f784Smrg	if (!xf86SetWeight(pScrn, zeros, masks))
5957104f784Smrg	    LEAVE(FALSE);
59609885543Smrg    }
59709885543Smrg
5987104f784Smrg    if (!xf86SetDefaultVisual(pScrn, -1))
5997104f784Smrg	LEAVE(FALSE);
60009885543Smrg
60109885543Smrg    /* We don't currently support DirectColor at > 8bpp */
6027104f784Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
60309885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) "
60409885543Smrg		   "is not supported at depth %d\n",
60509885543Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
6067104f784Smrg	LEAVE(FALSE);
60709885543Smrg    }
60809885543Smrg
60909885543Smrg    /* We use a programmable clock */
61009885543Smrg    pScrn->progClock = TRUE;
61109885543Smrg
61209885543Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
61309885543Smrg    xf86CollectOptions(pScrn, NULL);
61409885543Smrg
61509885543Smrg    /* Set the bits per RGB for 8bpp mode */
6167104f784Smrg    if (pScrn->depth == 8){
6177104f784Smrg	pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
6187104f784Smrg    }else if(pScrn->depth == 16){
6197104f784Smrg	/* Use 8 bit LUT for gamma correction*/
6207104f784Smrg	pScrn->rgbBits = 8;
62109885543Smrg    }
62209885543Smrg
62309885543Smrg    /* Process the options */
62409885543Smrg    if (!(pSmi->Options = xalloc(sizeof(SMIOptions))))
6257104f784Smrg	LEAVE(FALSE);
6267104f784Smrg
62709885543Smrg    memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
62809885543Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
62909885543Smrg
6307104f784Smrg    /* Enable pci burst by default */
6317104f784Smrg    from = X_DEFAULT;
6327104f784Smrg    pSmi->PCIBurst = TRUE;
6337104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst))
6347104f784Smrg	from = X_CONFIG;
6357104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n",
6367104f784Smrg	       pSmi->PCIBurst ? "en" : "dis");
63709885543Smrg
6387104f784Smrg    /* Pci retry enabled by default if pci burst also enabled */
6397104f784Smrg    from = X_DEFAULT;
6407104f784Smrg    pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE;
6417104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) {
6427104f784Smrg	from = X_CONFIG;
6437104f784Smrg	if (pSmi->PCIRetry && !pSmi->PCIBurst) {
6447104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
6457104f784Smrg		       "\"pci_retry\" option requires \"pci_burst\".\n");
6467104f784Smrg	    pSmi->PCIRetry = FALSE;
64709885543Smrg	}
64809885543Smrg    }
6497104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n",
6507104f784Smrg	       pSmi->PCIRetry ? "en" : "dis");
65109885543Smrg
65209885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) {
65309885543Smrg	pSmi->NoAccel = TRUE;
65409885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
65509885543Smrg		   "disabled\n");
65609885543Smrg    } else {
65709885543Smrg	pSmi->NoAccel = FALSE;
65809885543Smrg    }
65909885543Smrg
6607104f784Smrg    if (IS_MSOC(pSmi)) {
6617104f784Smrg	from = X_DEFAULT;
6627104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
6637104f784Smrg	    from = X_CONFIG;
6647104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n",
6657104f784Smrg		   pSmi->UseFBDev ? "enabled" : "disabled");
6667104f784Smrg    }
6677104f784Smrg
6687104f784Smrg    from = X_CONFIG;
6697104f784Smrg    pSmi->HwCursor = TRUE;
6707104f784Smrg    /* SWCursor overrides HWCusor if both specified */
6717104f784Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
6727104f784Smrg	pSmi->HwCursor = FALSE;
6737104f784Smrg    else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
6747104f784Smrg	from = X_DEFAULT;
67509885543Smrg
6767104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
6777104f784Smrg	       pSmi->HwCursor ? "Hard" : "Soft");
67809885543Smrg
67909885543Smrg    if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
68009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
68109885543Smrg		   "0x%08X\n", pSmi->videoKey);
68209885543Smrg    } else {
68309885543Smrg	pSmi->videoKey = (1 << pScrn->offset.red) |
68409885543Smrg			 (1 << pScrn->offset.green) |
68509885543Smrg			 (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
68609885543Smrg			 << pScrn->offset.blue);
68709885543Smrg    }
68809885543Smrg
68909885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) {
69009885543Smrg	pSmi->ByteSwap = TRUE;
69109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
69209885543Smrg    } else {
69309885543Smrg	pSmi->ByteSwap = FALSE;
69409885543Smrg    }
69509885543Smrg
69609885543Smrg    /* CZ 26.10.2001: interlaced video */
69709885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) {
69809885543Smrg	pSmi->interlaced = TRUE;
69909885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
70009885543Smrg    } else {
70109885543Smrg	pSmi->interlaced = FALSE;
70209885543Smrg    }
70309885543Smrg    /* end CZ */
70409885543Smrg
7057104f784Smrg    if (IS_MSOC(pSmi))
7067104f784Smrg	pSmi->useBIOS = FALSE;
7077104f784Smrg    else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) {
70809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
70909885543Smrg		   pSmi->useBIOS ? "enabled" : "disabled");
7107104f784Smrg    }
7117104f784Smrg    else if(pSmi->Chipset == SMI_LYNX3DM){
7127104f784Smrg	/* Default to UseBIOS disabled. */
7137104f784Smrg	pSmi->useBIOS = FALSE;
7147104f784Smrg    }
7157104f784Smrg    else {
71609885543Smrg	/* Default to UseBIOS enabled. */
71709885543Smrg	pSmi->useBIOS = TRUE;
71809885543Smrg    }
71909885543Smrg
7207104f784Smrg    if (pSmi->useBIOS) {
7217104f784Smrg	if (xf86LoadSubModule(pScrn,"int10")) {
7227104f784Smrg	    xf86LoaderReqSymLists(int10Symbols,NULL);
7237104f784Smrg	    pSmi->pInt10 = xf86InitInt10(pEnt->index);
7247104f784Smrg	}
72509885543Smrg
7267104f784Smrg	if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
7277104f784Smrg	    xf86LoaderReqSymLists(vbeSymbols, NULL);
7287104f784Smrg	    pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
7297104f784Smrg	}
73009885543Smrg
7317104f784Smrg	if(!pSmi->pVbe){
7327104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n");
7337104f784Smrg	    pSmi->useBIOS = FALSE;
7347104f784Smrg	}
73509885543Smrg    }
73609885543Smrg
73709885543Smrg    xf86RegisterResources(pEnt->index, NULL, ResExclusive);
73809885543Smrg/*  xf86SetOperatingState(resVgaIo, pEnt->index, ResUnusedOpr); */
73909885543Smrg/*  xf86SetOperatingState(resVgaMem, pEnt->index, ResDisableOpr); */
74009885543Smrg
74109885543Smrg    /*
74209885543Smrg     * Set the Chipset and ChipRev, allowing config file entries to
74309885543Smrg     * override.
74409885543Smrg     */
74509885543Smrg    if (pEnt->device->chipset && *pEnt->device->chipset) {
74609885543Smrg	pScrn->chipset = pEnt->device->chipset;
74709885543Smrg	pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
74809885543Smrg	from = X_CONFIG;
7497104f784Smrg    }
7507104f784Smrg    else if (pEnt->device->chipID >= 0) {
75109885543Smrg	pSmi->Chipset = pEnt->device->chipID;
75209885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
75309885543Smrg	from = X_CONFIG;
75409885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
75509885543Smrg		   pSmi->Chipset);
7567104f784Smrg    }
7577104f784Smrg    else {
75809885543Smrg	from = X_PROBED;
7597104f784Smrg	pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
76009885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
76109885543Smrg    }
76209885543Smrg
76309885543Smrg    if (pEnt->device->chipRev >= 0) {
76409885543Smrg	pSmi->ChipRev = pEnt->device->chipRev;
76509885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
76609885543Smrg		   pSmi->ChipRev);
76709885543Smrg    }
7687104f784Smrg    else
7697104f784Smrg        pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo);
77009885543Smrg    xfree(pEnt);
77109885543Smrg
77209885543Smrg    /*
77309885543Smrg     * This shouldn't happen because such problems should be caught in
77409885543Smrg     * SMI_Probe(), but check it just in case.
77509885543Smrg     */
77609885543Smrg    if (pScrn->chipset == NULL) {
77709885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
77809885543Smrg				"recognised\n", pSmi->Chipset);
7797104f784Smrg	LEAVE(FALSE);
78009885543Smrg    }
78109885543Smrg
78209885543Smrg    if (pSmi->Chipset < 0) {
78309885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
78409885543Smrg		   "recognised\n", pScrn->chipset);
7857104f784Smrg	LEAVE(FALSE);
78609885543Smrg    }
78709885543Smrg
78809885543Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
78909885543Smrg
7907104f784Smrg#ifndef XSERVER_LIBPCIACCESS
79109885543Smrg    pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
79209885543Smrg		   	  pSmi->PciInfo->func);
7937104f784Smrg#endif
79409885543Smrg
7957104f784Smrg    from = X_DEFAULT;
7967104f784Smrg    if(pSmi->Chipset == SMI_LYNX3DM &&
7977104f784Smrg       pScrn->bitsPerPixel == 16)
79809885543Smrg	pSmi->Dualhead = TRUE;
7997104f784Smrg    else
8007104f784Smrg	pSmi->Dualhead = FALSE;
8017104f784Smrg
8027104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead))
8037104f784Smrg	from = X_CONFIG;
8047104f784Smrg
8057104f784Smrg    if (IS_MSOC(pSmi)) {
8067104f784Smrg	pSmi->lcd = TRUE;
8077104f784Smrg	if (pSmi->Dualhead && pSmi->UseFBDev) {
8087104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
8097104f784Smrg		       "Dual head disabled in fbdev mode\n");
8107104f784Smrg	    pSmi->Dualhead = FALSE;
8117104f784Smrg	}
8127104f784Smrg	/* FIXME Randr cursor code only works properly when argb cursors
8137104f784Smrg	 * are also supported.
8147104f784Smrg	 * FIXME This probably is a randr cursor bug, and since access to
8157104f784Smrg	 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor
8167104f784Smrg	 * field is not available, one cannot easily workaround the problem,
8177104f784Smrg	 * so, just disable it...
8187104f784Smrg	 * TODO Check with a X Server newer then 1.4.0.90 (that is being
8197104f784Smrg	 * used in the 502 OEM image).
8207104f784Smrg	 * */
8217104f784Smrg	if (pSmi->Dualhead && pSmi->HwCursor) {
8227104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
8237104f784Smrg		       "HW Cursor disabled in dual head mode\n");
8247104f784Smrg	    pSmi->HwCursor = FALSE;
8257104f784Smrg	}
8267104f784Smrg    }
8277104f784Smrg    else if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
8287104f784Smrg	/* tweak options for dualhead */
8297104f784Smrg	if (pSmi->Dualhead) {
8307104f784Smrg	    pSmi->useBIOS = FALSE;
8317104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n");
8327104f784Smrg	    pSmi->HwCursor = FALSE;
8337104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n");
8347104f784Smrg	    if (pScrn->bitsPerPixel != 16) {
8357104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at "
8367104f784Smrg			   "depth 16\n");
8377104f784Smrg		LEAVE(FALSE);
8387104f784Smrg	    }
8397104f784Smrg	}
84009885543Smrg    }
8417104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n",
8427104f784Smrg	       pSmi->Dualhead ? "en" : "dis");
84309885543Smrg
8447104f784Smrg    if (!pSmi->NoAccel) {
8457104f784Smrg	char *strptr;
8467104f784Smrg
8477104f784Smrg	from = X_DEFAULT;
8487104f784Smrg	if ((strptr = (char *)xf86GetOptValString(pSmi->Options,
8497104f784Smrg						  OPTION_ACCELMETHOD))) {
8507104f784Smrg	    if (!xf86NameCmp(strptr,"XAA")) {
8517104f784Smrg		from = X_CONFIG;
8527104f784Smrg		pSmi->useEXA = FALSE;
8537104f784Smrg	    } else if(!xf86NameCmp(strptr,"EXA")) {
8547104f784Smrg		from = X_CONFIG;
8557104f784Smrg		pSmi->useEXA = TRUE;
8567104f784Smrg	    }
85709885543Smrg	}
8587104f784Smrg
8597104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
8607104f784Smrg		pSmi->useEXA ? "EXA" : "XAA");
86109885543Smrg    }
86209885543Smrg
8637104f784Smrg    if (IS_MSOC(pSmi)) {
8647104f784Smrg	pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead;
8657104f784Smrg	from = X_DEFAULT;
8667104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) {
8677104f784Smrg	    from = X_CONFIG;
8687104f784Smrg
8697104f784Smrg	    /* FIXME */
8707104f784Smrg	    if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) {
8717104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
8727104f784Smrg			   "CSCVideo requires XAA or EXA in single head mode.\n");
8737104f784Smrg		pSmi->CSCVideo = FALSE;
8747104f784Smrg	    }
8757104f784Smrg	}
87609885543Smrg
8777104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n",
8787104f784Smrg		   pSmi->CSCVideo ? "en" : "dis");
8797104f784Smrg    }
88009885543Smrg
8817104f784Smrg    SMI_MapMmio(pScrn);
8827104f784Smrg    SMI_DetectMem(pScrn);
8837104f784Smrg    SMI_MapMem(pScrn);
8847104f784Smrg    SMI_DisableVideo(pScrn);
88509885543Smrg
88609885543Smrg    /* detect the panel size */
88709885543Smrg    SMI_DetectPanelSize(pScrn);
88809885543Smrg
8897104f784Smrg    if(!IS_MSOC(pSmi)){
8907104f784Smrg	if (xf86LoadSubModule(pScrn, "i2c")) {
8917104f784Smrg	    xf86LoaderReqSymLists(i2cSymbols, NULL);
8927104f784Smrg	    SMI_I2CInit(pScrn);
8937104f784Smrg	}
8947104f784Smrg	if (xf86LoadSubModule(pScrn, "ddc")) {
8957104f784Smrg	    xf86LoaderReqSymLists(ddcSymbols, NULL);
8967104f784Smrg	}
89709885543Smrg    }
89809885543Smrg
89909885543Smrg    /*
90009885543Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
90109885543Smrg     */
90209885543Smrg    {
90309885543Smrg	Gamma zeros = { 0.0, 0.0, 0.0 };
90409885543Smrg
90509885543Smrg	if (!xf86SetGamma(pScrn, zeros)) {
90609885543Smrg	    SMI_EnableVideo(pScrn);
90709885543Smrg	    SMI_UnmapMem(pScrn);
9087104f784Smrg	    LEAVE(FALSE);
90909885543Smrg	}
91009885543Smrg    }
91109885543Smrg
9127104f784Smrg    SMI_DetectMCLK(pScrn);
91309885543Smrg
91409885543Smrg    /*
91509885543Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
91609885543Smrg     * and what sort of modes they can be used for.
91709885543Smrg     */
9187104f784Smrg    pSmi->clockRange.next = NULL;
9197104f784Smrg    pSmi->clockRange.minClock = 20000;
92009885543Smrg
9217104f784Smrg    if (SMI_LYNXM_SERIES(pSmi->Chipset) ||
9227104f784Smrg	IS_MSOC(pSmi))
9237104f784Smrg	pSmi->clockRange.maxClock = 200000;
92409885543Smrg    else
9257104f784Smrg        pSmi->clockRange.maxClock = 135000;
92609885543Smrg
9277104f784Smrg    pSmi->clockRange.clockIndex = -1;
9287104f784Smrg    pSmi->clockRange.interlaceAllowed = FALSE;
9297104f784Smrg    pSmi->clockRange.doubleScanAllowed = FALSE;
93009885543Smrg
9317104f784Smrg    if(!SMI_CrtcPreInit(pScrn))
9327104f784Smrg	LEAVE(FALSE);
9337104f784Smrg
9347104f784Smrg    if(!SMI_OutputPreInit(pScrn))
9357104f784Smrg	LEAVE(FALSE);
9367104f784Smrg
9377104f784Smrg    /* Only allow growing the screen dimensions if EXA is being used */
9387104f784Smrg    if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){
93909885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
9407104f784Smrg	LEAVE(FALSE);
94109885543Smrg    }
94209885543Smrg
94309885543Smrg
9447104f784Smrg    SMI_EnableVideo(pScrn);
9457104f784Smrg    SMI_UnmapMem(pScrn);
9467104f784Smrg
9477104f784Smrg    if(pSmi->pVbe){
9487104f784Smrg       vbeFree(pSmi->pVbe);
9497104f784Smrg       pSmi->pVbe = NULL;
9507104f784Smrg    }
9517104f784Smrg    if(pSmi->pInt10){
9527104f784Smrg       xf86FreeInt10(pSmi->pInt10);
9537104f784Smrg       pSmi->pInt10 = NULL;
9547104f784Smrg    }
95509885543Smrg
95609885543Smrg    /* Set display resolution */
95709885543Smrg    xf86SetDpi(pScrn, 0, 0);
95809885543Smrg
9597104f784Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
96009885543Smrg	SMI_FreeRec(pScrn);
9617104f784Smrg	LEAVE(FALSE);
96209885543Smrg    }
96309885543Smrg
96409885543Smrg    xf86LoaderReqSymLists(fbSymbols, NULL);
96509885543Smrg
96609885543Smrg    /* Load XAA or EXA if needed */
96709885543Smrg    if (!pSmi->NoAccel) {
96809885543Smrg	if (!pSmi->useEXA) {
96909885543Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
97009885543Smrg		SMI_FreeRec(pScrn);
9717104f784Smrg		LEAVE(FALSE);
97209885543Smrg	    }
97309885543Smrg	    xf86LoaderReqSymLists(xaaSymbols, NULL);
97409885543Smrg	} else {
97509885543Smrg	    XF86ModReqInfo req;
97609885543Smrg	    int errmaj, errmin;
97709885543Smrg
97809885543Smrg	    memset(&req, 0, sizeof(XF86ModReqInfo));
97909885543Smrg	    req.majorversion = 2;
9807104f784Smrg	    req.minorversion = 1;
98109885543Smrg
98209885543Smrg	    if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
98309885543Smrg				&req, &errmaj, &errmin)) {
98409885543Smrg		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
98509885543Smrg		SMI_FreeRec(pScrn);
9867104f784Smrg		LEAVE(FALSE);
98709885543Smrg	    }
98809885543Smrg	    xf86LoaderReqSymLists(exaSymbols, NULL);
98909885543Smrg	}
99009885543Smrg    }
99109885543Smrg
99209885543Smrg    /* Load ramdac if needed */
9937104f784Smrg    if (pSmi->HwCursor) {
99409885543Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
99509885543Smrg	    SMI_FreeRec(pScrn);
9967104f784Smrg	    LEAVE(FALSE);
99709885543Smrg	}
99809885543Smrg    }
99909885543Smrg
10007104f784Smrg    LEAVE(TRUE);
100109885543Smrg}
100209885543Smrg
100309885543Smrg/*
100409885543Smrg * This is called when VT switching back to the X server.  Its job is to
100509885543Smrg * reinitialise the video mode. We may wish to unmap video/MMIO memory too.
100609885543Smrg */
100709885543Smrg
100809885543Smrgstatic Bool
100909885543SmrgSMI_EnterVT(int scrnIndex, int flags)
101009885543Smrg{
101109885543Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
101209885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
101309885543Smrg
10147104f784Smrg    ENTER();
101509885543Smrg
101609885543Smrg    /* Enable MMIO and map memory */
101709885543Smrg    SMI_MapMem(pScrn);
101809885543Smrg
10197104f784Smrg    pSmi->Save(pScrn);
102009885543Smrg
10217104f784Smrg    /* FBBase may have changed after remapping the memory */
10227104f784Smrg    pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
10237104f784Smrg				       -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
10247104f784Smrg    pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
102509885543Smrg
10267104f784Smrg    if(pSmi->useEXA)
10277104f784Smrg       pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
102809885543Smrg
10297104f784Smrg    /* Do the CRTC independent initialization */
10307104f784Smrg    if(!SMI_HWInit(pScrn))
10317104f784Smrg	LEAVE(FALSE);
103209885543Smrg
10337104f784Smrg    /* Initialize the chosen modes */
10347104f784Smrg    if (!xf86SetDesiredModes(pScrn))
10357104f784Smrg	LEAVE(FALSE);
103609885543Smrg
10377104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
10387104f784Smrg		   "Done writing mode.  Register dump:\n");
10397104f784Smrg    SMI_PrintRegs(pScrn);
104009885543Smrg
104109885543Smrg    /* Reset the grapics engine */
104209885543Smrg    if (!pSmi->NoAccel)
104309885543Smrg	SMI_EngineReset(pScrn);
104409885543Smrg
10457104f784Smrg    LEAVE(TRUE);
104609885543Smrg}
104709885543Smrg
104809885543Smrg/*
104909885543Smrg * This is called when VT switching away from the X server.  Its job is to
105009885543Smrg * restore the previous (text) mode. We may wish to remap video/MMIO memory
105109885543Smrg * too.
105209885543Smrg */
105309885543Smrg
105409885543Smrgstatic void
105509885543SmrgSMI_LeaveVT(int scrnIndex, int flags)
105609885543Smrg{
10577104f784Smrg    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
10587104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
105909885543Smrg
10607104f784Smrg    ENTER();
106109885543Smrg
10627104f784Smrg    SMI_AccelSync(pScrn);
106309885543Smrg
10647104f784Smrg    /* Ensure that the rotation BlockHandler is unwrapped, and the shadow
10657104f784Smrg       pixmaps are deallocated, as the video memory is going to be
10667104f784Smrg       unmapped.  */
10677104f784Smrg    xf86RotateCloseScreen(pScrn->pScreen);
106809885543Smrg
10697104f784Smrg    /* Pixmaps that by chance get allocated near the former aperture
10707104f784Smrg       address shouldn't be considered offscreen. */
10717104f784Smrg    if(pSmi->useEXA)
10727104f784Smrg       pSmi->EXADriverPtr->memoryBase=NULL;
107309885543Smrg
10747104f784Smrg    /* Clear frame buffer */
10757104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
10767104f784Smrg
10777104f784Smrg    if (!IS_MSOC(pSmi)) {
10787104f784Smrg	vgaHWPtr	hwp = VGAHWPTR(pScrn);
10797104f784Smrg
10807104f784Smrg	SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
108109885543Smrg    }
10827104f784Smrg    else
10837104f784Smrg	SMI501_WriteMode(pScrn, pSmi->save);
108409885543Smrg
108509885543Smrg    SMI_UnmapMem(pScrn);
108609885543Smrg
10877104f784Smrg    LEAVE();
108809885543Smrg}
108909885543Smrg
109009885543Smrgstatic void
10917104f784SmrgSMI_DetectPanelSize(ScrnInfoPtr pScrn)
109209885543Smrg{
10937104f784Smrg    char	*s;
10947104f784Smrg    int		 width, height;
10957104f784Smrg    SMIPtr	 pSmi = SMIPTR(pScrn);
109609885543Smrg
10977104f784Smrg    pSmi->lcdWidth  = 0;
10987104f784Smrg    pSmi->lcdHeight = 0;
10997104f784Smrg    if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) {
11007104f784Smrg	if (sscanf(s, "%dx%d", &width, &height) != 2)
11017104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
11027104f784Smrg		       "Invalid PanelSize option: %s\n", s);
11037104f784Smrg	else {
11047104f784Smrg	    pSmi->lcdWidth  = width;
11057104f784Smrg	    pSmi->lcdHeight = height;
110609885543Smrg	}
110709885543Smrg    }
110809885543Smrg
11097104f784Smrg    if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) {
11107104f784Smrg	/* panel size detection ... requires BIOS call on 730 hardware */
11117104f784Smrg	if (pSmi->Chipset == SMI_COUGAR3DR) {
11127104f784Smrg	    if (pSmi->pInt10 != NULL) {
11137104f784Smrg		pSmi->pInt10->num = 0x10;
11147104f784Smrg		pSmi->pInt10->ax  = 0x5F00;
11157104f784Smrg		pSmi->pInt10->bx  = 0;
11167104f784Smrg		pSmi->pInt10->cx  = 0;
11177104f784Smrg		pSmi->pInt10->dx  = 0;
11187104f784Smrg		xf86ExecX86int10(pSmi->pInt10);
11197104f784Smrg		if (pSmi->pInt10->ax == 0x005F) {
11207104f784Smrg		    switch (pSmi->pInt10->cx & 0x0F) {
11217104f784Smrg			case PANEL_640x480:
11227104f784Smrg			    pSmi->lcdWidth  = 640;
11237104f784Smrg			    pSmi->lcdHeight = 480;
11247104f784Smrg			    break;
11257104f784Smrg			case PANEL_800x600:
11267104f784Smrg			    pSmi->lcdWidth  = 800;
11277104f784Smrg			    pSmi->lcdHeight = 600;
11287104f784Smrg			    break;
11297104f784Smrg			case PANEL_1024x768:
11307104f784Smrg			    pSmi->lcdWidth  = 1024;
11317104f784Smrg			    pSmi->lcdHeight = 768;
11327104f784Smrg			    break;
11337104f784Smrg			case PANEL_1280x1024:
11347104f784Smrg			    pSmi->lcdWidth  = 1280;
11357104f784Smrg			    pSmi->lcdHeight = 1024;
11367104f784Smrg			    break;
11377104f784Smrg			case PANEL_1600x1200:
11387104f784Smrg			    pSmi->lcdWidth  = 1600;
11397104f784Smrg			    pSmi->lcdHeight = 1200;
11407104f784Smrg			    break;
11417104f784Smrg			case PANEL_1400x1050:
11427104f784Smrg			    pSmi->lcdWidth  = 1400;
11437104f784Smrg			    pSmi->lcdHeight = 1050;
11447104f784Smrg			    break;
11457104f784Smrg		    }
114609885543Smrg
11477104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
11487104f784Smrg			       "Detected panel size via BIOS: %d x %d\n",
11497104f784Smrg			       pSmi->lcdWidth, pSmi->lcdHeight);
115009885543Smrg		}
11517104f784Smrg		else
11527104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
11537104f784Smrg			       "BIOS error during 730 panel detection!\n");
115409885543Smrg	    }
11557104f784Smrg	    else  {
11567104f784Smrg		/* int10 support isn't setup on the second call to this function,
11577104f784Smrg		  o if this is the second call, don't do detection again */
11587104f784Smrg		if (pSmi->lcd == 0)
11597104f784Smrg		    /* If we get here, int10 support is not loaded or not working */
11607104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
11617104f784Smrg			       "No BIOS support for 730 panel detection!\n");
116209885543Smrg	    }
116309885543Smrg
11647104f784Smrg	    /* Set this to indicate that we've done the detection */
11657104f784Smrg	    pSmi->lcd = 1;
116609885543Smrg	}
11677104f784Smrg	else if (IS_MSOC(pSmi)) {
11687104f784Smrg	    pSmi->lcdWidth  = (READ_SCR(pSmi, PANEL_WWIDTH)  >> 16) & 2047;
11697104f784Smrg	    pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047;
117009885543Smrg	}
11717104f784Smrg	else {
11727104f784Smrg	    /* panel size detection for hardware other than 730 */
11737104f784Smrg	    pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
11747104f784Smrg				     0x31) & 0x01;
117509885543Smrg
11767104f784Smrg	    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
11777104f784Smrg			     0x30) & 0x01) {
11787104f784Smrg		pSmi->lcd <<= 1;
11797104f784Smrg	    }
11807104f784Smrg	    switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
11817104f784Smrg				 0x30) & 0x0C) {
11827104f784Smrg		case 0x00:
118309885543Smrg		    pSmi->lcdWidth  = 640;
118409885543Smrg		    pSmi->lcdHeight = 480;
118509885543Smrg		    break;
11867104f784Smrg		case 0x04:
118709885543Smrg		    pSmi->lcdWidth  = 800;
118809885543Smrg		    pSmi->lcdHeight = 600;
118909885543Smrg		    break;
11907104f784Smrg		case 0x08:
11917104f784Smrg		    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
11927104f784Smrg				     0x74) & 0x02) {
11937104f784Smrg			pSmi->lcdWidth  = 1024;
11947104f784Smrg			pSmi->lcdHeight = 600;
11957104f784Smrg		    }
11967104f784Smrg		    else {
11977104f784Smrg			pSmi->lcdWidth  = 1024;
11987104f784Smrg			pSmi->lcdHeight = 768;
11997104f784Smrg		    }
120009885543Smrg		    break;
12017104f784Smrg		case 0x0C:
120209885543Smrg		    pSmi->lcdWidth  = 1280;
120309885543Smrg		    pSmi->lcdHeight = 1024;
120409885543Smrg		    break;
120509885543Smrg	    }
120609885543Smrg	}
120709885543Smrg    }
120809885543Smrg
12097104f784Smrg    if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0)
12107104f784Smrg	pSmi->lcdWidth = 1024;
12117104f784Smrg    if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0)
12127104f784Smrg	pSmi->lcdHeight = 768;
12137104f784Smrg
121409885543Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
121509885543Smrg	       (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
121609885543Smrg	       pSmi->lcdWidth, pSmi->lcdHeight);
121709885543Smrg
121809885543Smrg}
121909885543Smrg
12207104f784Smrgstatic void
12217104f784SmrgSMI_DetectMCLK(ScrnInfoPtr pScrn)
12227104f784Smrg{
12237104f784Smrg    double		real;
12247104f784Smrg    MSOCClockRec	clock;
12257104f784Smrg    int			mclk, mxclk;
12267104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
12277104f784Smrg
12287104f784Smrg    /* MCLK defaults */
12297104f784Smrg    if (pSmi->Chipset == SMI_LYNXEMplus){
12307104f784Smrg	/* The SM712 can be safely clocked up to 157MHz, according to
12317104f784Smrg	   Silicon Motion engineers. */
12327104f784Smrg	pSmi->MCLK = 157000;
12337104f784Smrg    }else
12347104f784Smrg	pSmi->MCLK = 0;
12357104f784Smrg
12367104f784Smrg    pSmi->MXCLK = 0;
12377104f784Smrg
12387104f784Smrg    /* MCLK from user settings */
12397104f784Smrg    if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
12407104f784Smrg	if (IS_MSOC(pSmi) || (int)real <= 120) {
12417104f784Smrg	    pSmi->MCLK = (int)(real * 1000.0);
12427104f784Smrg	} else {
12437104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
12447104f784Smrg		       "Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
12457104f784Smrg		       real);
12467104f784Smrg	}
12477104f784Smrg    }
12487104f784Smrg    mclk = pSmi->MCLK;
12497104f784Smrg
12507104f784Smrg    if (IS_MSOC(pSmi)) {
12517104f784Smrg	clock.value = READ_SCR(pSmi, CURRENT_CLOCK);
12527104f784Smrg	if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK,
12537104f784Smrg			      OPTUNITS_MHZ, &real))
12547104f784Smrg	    pSmi->MXCLK = (int)(real * 1000.0);
12557104f784Smrg    }
12567104f784Smrg
12577104f784Smrg    /* Already programmed MCLK */
12587104f784Smrg    if (pSmi->MCLK == 0) {
12597104f784Smrg	if (IS_MSOC(pSmi))
12607104f784Smrg	    mclk = ((clock.f.m_select ? 336 : 288) /
12617104f784Smrg		    ((clock.f.m_divider ? 3 : 1) <<
12627104f784Smrg		     (unsigned)clock.f.m_shift)) * 1000;
12637104f784Smrg	else {
12647104f784Smrg	    unsigned char	shift, m, n;
12657104f784Smrg
12667104f784Smrg	    m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
12677104f784Smrg	    n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
12687104f784Smrg	    switch (n >> 6) {
12697104f784Smrg		case 1:
12707104f784Smrg		    shift = 4;
12717104f784Smrg		    break;
12727104f784Smrg		case 2:
12737104f784Smrg		    shift = 2;
12747104f784Smrg		    break;
12757104f784Smrg		default:
12767104f784Smrg		    shift = 1;
12777104f784Smrg		    break;
12787104f784Smrg	    }
12797104f784Smrg	    n &= 0x3F;
12807104f784Smrg	    mclk = ((1431818 * m) / n / shift + 50) / 100;
12817104f784Smrg	}
12827104f784Smrg    }
12837104f784Smrg
12847104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0);
12857104f784Smrg    if (IS_MSOC(pSmi)) {
12867104f784Smrg	if (pSmi->MXCLK == 0) {
12877104f784Smrg	    mxclk = ((clock.f.m1_select ? 336 : 288) /
12887104f784Smrg		     ((clock.f.m1_divider ? 3 : 1) <<
12897104f784Smrg		      (unsigned)clock.f.m1_shift)) * 1000;
12907104f784Smrg	}
12917104f784Smrg	else
12927104f784Smrg	    mxclk = pSmi->MXCLK;
12937104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0);
12947104f784Smrg    }
12957104f784Smrg}
12967104f784Smrg
129709885543Smrgstatic Bool
12987104f784SmrgSMI_MapMmio(ScrnInfoPtr pScrn)
129909885543Smrg{
13007104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
13017104f784Smrg    CARD32	memBase;
130209885543Smrg
13037104f784Smrg    SMI_EnableMmio(pScrn);
130409885543Smrg
130509885543Smrg    switch (pSmi->Chipset) {
13067104f784Smrg	case SMI_COUGAR3DR:
13077104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
13087104f784Smrg	    pSmi->MapSize = 0x200000;
13097104f784Smrg	    break;
13107104f784Smrg	case SMI_LYNX3D:
13117104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000;
13127104f784Smrg	    pSmi->MapSize = 0x180000;
13137104f784Smrg	    break;
13147104f784Smrg	case SMI_LYNXEM:
13157104f784Smrg	case SMI_LYNXEMplus:
13167104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
13177104f784Smrg	    pSmi->MapSize = 0x400000;
13187104f784Smrg	    break;
13197104f784Smrg	case SMI_LYNX3DM:
13207104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
13217104f784Smrg	    pSmi->MapSize = 0x200000;
13227104f784Smrg	    break;
13237104f784Smrg	case SMI_MSOC:
13247104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
13257104f784Smrg	    pSmi->MapSize = 0x200000;
13267104f784Smrg	    break;
13277104f784Smrg	default:
13287104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
13297104f784Smrg	    pSmi->MapSize = 0x10000;
13307104f784Smrg	    break;
133109885543Smrg    }
13327104f784Smrg
13337104f784Smrg#ifndef XSERVER_LIBPCIACCESS
133409885543Smrg    pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
133509885543Smrg				  memBase, pSmi->MapSize);
13367104f784Smrg#else
13377104f784Smrg    {
13387104f784Smrg	void	**result = (void**)&pSmi->MapBase;
13397104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
13407104f784Smrg					     memBase,
13417104f784Smrg					     pSmi->MapSize,
13427104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE,
13437104f784Smrg					     result);
13447104f784Smrg
13457104f784Smrg	if (err)
13467104f784Smrg	    return (FALSE);
13477104f784Smrg    }
13487104f784Smrg#endif
134909885543Smrg
135009885543Smrg    if (pSmi->MapBase == NULL) {
135109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
135209885543Smrg		   "MMIO registers.\n");
13537104f784Smrg	return (FALSE);
135409885543Smrg    }
135509885543Smrg
135609885543Smrg    switch (pSmi->Chipset) {
13577104f784Smrg	case SMI_COUGAR3DR:
13587104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
13597104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
13607104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
13617104f784Smrg	    pSmi->FPRBase = pSmi->MapBase + 0x005800;
13627104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
13637104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
13647104f784Smrg	    pSmi->DataPortSize = 0x100000;
13657104f784Smrg	    break;
13667104f784Smrg	case SMI_LYNX3D:
13677104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
13687104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
13697104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
13707104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x040000;
13717104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x080000;
13727104f784Smrg	    pSmi->DataPortSize = 0x100000;
13737104f784Smrg	    break;
13747104f784Smrg	case SMI_LYNXEM:
13757104f784Smrg	case SMI_LYNXEMplus:
13767104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x008000;
13777104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x00C000;
13787104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x00E000;
13797104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x300000;
13807104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
13817104f784Smrg	    pSmi->DataPortSize = 0x8000 /*0x200000*/;
13827104f784Smrg	    break;
13837104f784Smrg	case SMI_LYNX3DM:
13847104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
13857104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
13867104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
13877104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
13887104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
13897104f784Smrg	    pSmi->DataPortSize = 0x100000;
13907104f784Smrg	    break;
13917104f784Smrg	case SMI_MSOC:
13927104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x100000;
13937104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000000;
13947104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x090000;
13957104f784Smrg	    pSmi->DCRBase = pSmi->MapBase + 0x080000;
13967104f784Smrg	    pSmi->SCRBase = pSmi->MapBase + 0x000000;
13977104f784Smrg	    pSmi->IOBase = 0;
13987104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x110000;
13997104f784Smrg	    pSmi->DataPortSize = 0x10000;
14007104f784Smrg	    break;
14017104f784Smrg	default:
14027104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x8000;
14037104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0xC000;
14047104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0xE000;
14057104f784Smrg	    pSmi->IOBase  = NULL;
14067104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase;
14077104f784Smrg	    pSmi->DataPortSize = 0x8000;
14087104f784Smrg	    break;
140909885543Smrg    }
14107104f784Smrg
141109885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
141209885543Smrg		   "Physical MMIO at 0x%08lX\n", (unsigned long)memBase);
141309885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
141409885543Smrg		   "Logical MMIO at %p - %p\n", pSmi->MapBase,
141509885543Smrg		   pSmi->MapBase + pSmi->MapSize - 1);
141609885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
141709885543Smrg		   "DPR=%p, VPR=%p, IOBase=%p\n",
141809885543Smrg		   pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase);
141909885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
142009885543Smrg		   "DataPort=%p - %p\n", pSmi->DataPortBase,
142109885543Smrg		   pSmi->DataPortBase + pSmi->DataPortSize - 1);
142209885543Smrg
14237104f784Smrg    return (TRUE);
14247104f784Smrg}
142509885543Smrg
14267104f784Smrgstatic Bool
14277104f784SmrgSMI_DetectMem(ScrnInfoPtr pScrn)
14287104f784Smrg{
14297104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
14307104f784Smrg    MessageType from;
143109885543Smrg
14327104f784Smrg    if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){
14337104f784Smrg	pSmi->videoRAMKBytes = pScrn->videoRam;
14347104f784Smrg	from = X_CONFIG;
14357104f784Smrg    }
14367104f784Smrg    else {
14377104f784Smrg	unsigned char	 config;
14387104f784Smrg	static int	 lynx3d_table[4]  = {  0, 2, 4, 6 };
14397104f784Smrg	static int	 lynx3dm_table[4] = { 16, 2, 4, 8 };
14407104f784Smrg	static int	 msoc_table[8]    = {  4, 8, 16, 32, 64, 2, 0, 0 };
14417104f784Smrg	static int	 default_table[4] = {  1, 2, 4, 0 };
14427104f784Smrg
14437104f784Smrg	if (IS_MSOC(pSmi)) {
14447104f784Smrg	    config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7;
14457104f784Smrg	    pSmi->videoRAMKBytes = msoc_table[config] * 1024 -
14467104f784Smrg		SHARED_USB_DMA_BUFFER_SIZE;
14477104f784Smrg	}
14487104f784Smrg	else {
14497104f784Smrg	    config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
14507104f784Smrg	    switch (pSmi->Chipset) {
14517104f784Smrg		case SMI_LYNX3D:
14527104f784Smrg		    pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 +
14537104f784Smrg			512;
14547104f784Smrg		    break;
14557104f784Smrg		case SMI_LYNX3DM:
14567104f784Smrg		    pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024;
14577104f784Smrg		    break;
14587104f784Smrg		case SMI_COUGAR3DR:
14597104f784Smrg		    /* DANGER - Cougar3DR BIOS is broken - hardcode video ram
14607104f784Smrg		     * size per instructions from Silicon Motion engineers */
14617104f784Smrg		    pSmi->videoRAMKBytes = 16 * 1024;
14627104f784Smrg		    break;
14637104f784Smrg		default:
14647104f784Smrg		    pSmi->videoRAMKBytes = default_table[config >> 6] * 1024;
14657104f784Smrg		    break;
14667104f784Smrg	    }
146709885543Smrg	}
14687104f784Smrg	from = X_PROBED;
14697104f784Smrg    }
147009885543Smrg
14717104f784Smrg    pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
14727104f784Smrg    pScrn->videoRam     = pSmi->videoRAMKBytes;
14737104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
14747104f784Smrg	       "videoram: %dkB\n", pSmi->videoRAMKBytes);
147509885543Smrg
14767104f784Smrg    return (TRUE);
14777104f784Smrg}
147809885543Smrg
14797104f784SmrgBool
14807104f784SmrgSMI_MapMem(ScrnInfoPtr pScrn)
14817104f784Smrg{
14827104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
14837104f784Smrg    vgaHWPtr hwp;
148409885543Smrg
14857104f784Smrg    ENTER();
14867104f784Smrg
14877104f784Smrg    if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE)
14887104f784Smrg	LEAVE(FALSE);
14897104f784Smrg
14907104f784Smrg    pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
14917104f784Smrg
14927104f784Smrg    if (pSmi->Chipset == SMI_LYNX3DM)
14937104f784Smrg	pSmi->fbMapOffset = 0x200000;
14947104f784Smrg    else
14957104f784Smrg	pSmi->fbMapOffset = 0x0;
14967104f784Smrg
14977104f784Smrg#ifndef XSERVER_LIBPCIACCESS
14987104f784Smrg    pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex,
14997104f784Smrg				 VIDMEM_FRAMEBUFFER,
15007104f784Smrg				 pSmi->PciTag,
15017104f784Smrg				 pScrn->memPhysBase + pSmi->fbMapOffset,
15027104f784Smrg				 pSmi->videoRAMBytes);
15037104f784Smrg#else
15047104f784Smrg    {
15057104f784Smrg	void	**result = (void**)&pSmi->FBBase;
15067104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
15077104f784Smrg					     pScrn->memPhysBase +
15087104f784Smrg					     pSmi->fbMapOffset,
15097104f784Smrg					     pSmi->videoRAMBytes,
15107104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE |
15117104f784Smrg					     PCI_DEV_MAP_FLAG_WRITE_COMBINE,
15127104f784Smrg					     result);
15137104f784Smrg
15147104f784Smrg	if (err)
15157104f784Smrg	    LEAVE(FALSE);
15167104f784Smrg    }
15177104f784Smrg#endif
15187104f784Smrg
15197104f784Smrg    if (pSmi->FBBase == NULL) {
15207104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
15217104f784Smrg		   "Internal error: could not map framebuffer.\n");
15227104f784Smrg	LEAVE(FALSE);
15237104f784Smrg    }
15247104f784Smrg
15257104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
15267104f784Smrg		   "Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
15277104f784Smrg		   pScrn->memPhysBase, pSmi->fbMapOffset);
15287104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
15297104f784Smrg		   "Logical frame buffer at %p - %p\n", pSmi->FBBase,
15307104f784Smrg		   pSmi->FBBase + pSmi->videoRAMBytes - 1);
15317104f784Smrg
15327104f784Smrg    if (IS_MSOC(pSmi)) {
15337104f784Smrg	/* Reserve space for panel cursr, and crt if in dual head mode */
15347104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
15357104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15367104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE);
15377104f784Smrg#else
15387104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15397104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE);
15407104f784Smrg
15417104f784Smrg# if SMI501_CLI_DEBUG
15427104f784Smrg	if (pSmi->useEXA) {
15437104f784Smrg	    pSmi->batch_active = FALSE;
15447104f784Smrg	    pSmi->batch_length = 4096;
15457104f784Smrg	    pSmi->FBReserved -= pSmi->batch_length << 3;
15467104f784Smrg	    pSmi->batch_offset = pSmi->FBReserved;
15477104f784Smrg	    pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset);
15487104f784Smrg	    pSmi->batch_finish = -1;
15497104f784Smrg	    pSmi->batch_index = 0;
15507104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
15517104f784Smrg		       "Using command list interpreter debug code\n");
15527104f784Smrg	}
15537104f784Smrg# endif
15547104f784Smrg
15557104f784Smrg#endif
15567104f784Smrg    }
15577104f784Smrg    else {
15587104f784Smrg	/* Set up offset to hwcursor memory area, at the end of
15597104f784Smrg	 * the frame buffer.
15607104f784Smrg	 */
15617104f784Smrg	pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE;
156209885543Smrg	/* set up the fifo reserved space */
156309885543Smrg	if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ {
156409885543Smrg	    CARD32 fifoOffset = 0;
15657104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15667104f784Smrg				       0x46) << 3;
15677104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15687104f784Smrg				       0x47) << 11;
15697104f784Smrg	    fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15707104f784Smrg					0x49) & 0x1C) << 17;
157109885543Smrg	    pSmi->FBReserved = fifoOffset;	/* PDR#1074 */
157209885543Smrg	}
15737104f784Smrg	else
15747104f784Smrg	    pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
157509885543Smrg
15767104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n",
15777104f784Smrg		   (unsigned long)pSmi->FBCursorOffset);
157809885543Smrg
15797104f784Smrg	/* Assign hwp->MemBase & IOBase here */
15807104f784Smrg	hwp = VGAHWPTR(pScrn);
15817104f784Smrg	if (pSmi->IOBase != NULL)
15827104f784Smrg	    vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
15837104f784Smrg	vgaHWGetIOBase(hwp);
158409885543Smrg
15857104f784Smrg	/* Map the VGA memory when the primary video */
15867104f784Smrg	if (xf86IsPrimaryPci(pSmi->PciInfo)) {
15877104f784Smrg	    hwp->MapSize = 0x10000;
15887104f784Smrg	    if (!vgaHWMapMem(pScrn))
15897104f784Smrg		LEAVE(FALSE);
15907104f784Smrg	    pSmi->PrimaryVidMapped = TRUE;
159109885543Smrg	}
159209885543Smrg    }
159309885543Smrg
15947104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n",
15957104f784Smrg	       (unsigned long)pSmi->FBReserved);
15967104f784Smrg
15977104f784Smrg    LEAVE(TRUE);
159809885543Smrg}
159909885543Smrg
160009885543Smrg/* UnMapMem - contains half of pre-4.0 EnterLeave function.  The EnterLeave
160109885543Smrg * function which en/disable access to IO ports and ext. regs
160209885543Smrg */
160309885543Smrg
16047104f784Smrgvoid
160509885543SmrgSMI_UnmapMem(ScrnInfoPtr pScrn)
160609885543Smrg{
160709885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
160809885543Smrg
16097104f784Smrg    ENTER();
161009885543Smrg
161109885543Smrg    /* Unmap VGA mem if mapped. */
161209885543Smrg    if (pSmi->PrimaryVidMapped) {
161309885543Smrg	vgaHWUnmapMem(pScrn);
161409885543Smrg	pSmi->PrimaryVidMapped = FALSE;
161509885543Smrg    }
161609885543Smrg
161709885543Smrg    SMI_DisableMmio(pScrn);
161809885543Smrg
16197104f784Smrg    if (pSmi->MapBase) {
16207104f784Smrg#ifndef XSERVER_LIBPCIACCESS
16217104f784Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase,
16227104f784Smrg			pSmi->MapSize);
16237104f784Smrg#else
16247104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase,
16257104f784Smrg			       pSmi->MapSize);
16267104f784Smrg#endif
16277104f784Smrg	pSmi->MapBase = NULL;
16287104f784Smrg    }
16297104f784Smrg
16307104f784Smrg    if (pSmi->FBBase) {
16317104f784Smrg#ifndef XSERVER_LIBPCIACCESS
163209885543Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
163309885543Smrg			pSmi->videoRAMBytes);
16347104f784Smrg#else
16357104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase,
16367104f784Smrg			       pSmi->videoRAMBytes);
16377104f784Smrg#endif
16387104f784Smrg	pSmi->FBBase = NULL;
163909885543Smrg    }
164009885543Smrg
16417104f784Smrg    LEAVE();
164209885543Smrg}
164309885543Smrg
164409885543Smrg/* This gets called at the start of each server generation. */
164509885543Smrg
164609885543Smrgstatic Bool
164709885543SmrgSMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
164809885543Smrg{
16497104f784Smrg    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
16507104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
16517104f784Smrg    EntityInfoPtr	pEnt;
165209885543Smrg
16537104f784Smrg    ENTER();
165409885543Smrg
165509885543Smrg    /* Map MMIO regs and framebuffer */
16567104f784Smrg    if (!SMI_MapMem(pScrn))
16577104f784Smrg	LEAVE(FALSE);
165809885543Smrg
165909885543Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
166009885543Smrg
16617104f784Smrg    if (!pSmi->pInt10 && pSmi->useBIOS) {
16627104f784Smrg	pSmi->pInt10 = xf86InitInt10(pEnt->index);
166309885543Smrg    }
16647104f784Smrg    if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
16657104f784Smrg	pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
166609885543Smrg    }
166709885543Smrg
16687104f784Smrg    /* Save the chip/graphics state */
16697104f784Smrg    pSmi->Save(pScrn);
167009885543Smrg
16717104f784Smrg    /* Fill in some needed pScrn fields */
16727104f784Smrg    pScrn->vtSema = TRUE;
16737104f784Smrg    pScrn->pScreen = pScreen;
167409885543Smrg
16757104f784Smrg    pSmi->Bpp = pScrn->bitsPerPixel >> 3;
16767104f784Smrg    pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
167709885543Smrg
16787104f784Smrg    pSmi->fbArea = NULL;
16797104f784Smrg    pSmi->FBOffset = 0;
16807104f784Smrg    pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
168109885543Smrg
16827104f784Smrg    /* Clear frame buffer */
16837104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
168409885543Smrg
168509885543Smrg    /*
16867104f784Smrg     * The next step is to setup the screen's visuals, and initialise the
16877104f784Smrg     * framebuffer code.  In cases where the framebuffer's default choises for
16887104f784Smrg     * things like visual layouts and bits per RGB are OK, this may be as simple
16897104f784Smrg     * as calling the framebuffer's ScreenInit() function.  If not, the visuals
16907104f784Smrg     * will need to be setup before calling a fb ScreenInit() function and fixed
16917104f784Smrg     * up after.
16927104f784Smrg     */
169309885543Smrg
16947104f784Smrg    /*
16957104f784Smrg     * Reset the visual list.
16967104f784Smrg     */
16977104f784Smrg    miClearVisualTypes();
169809885543Smrg
16997104f784Smrg    /* Setup the visuals we support. */
170009885543Smrg
17017104f784Smrg    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
17027104f784Smrg			  pScrn->rgbBits, pScrn->defaultVisual))
17037104f784Smrg	LEAVE(FALSE);
170409885543Smrg
17057104f784Smrg    if (!miSetPixmapDepths ())
17067104f784Smrg	LEAVE(FALSE);
170709885543Smrg
17087104f784Smrg    /*
17097104f784Smrg     * Call the framebuffer layer's ScreenInit function
17107104f784Smrg     */
171109885543Smrg
17127104f784Smrg    DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
17137104f784Smrg	  pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
17147104f784Smrg    if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
17157104f784Smrg		     pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
17167104f784Smrg	LEAVE(FALSE);
171709885543Smrg
17187104f784Smrg    xf86SetBlackWhitePixels(pScreen);
171909885543Smrg
17207104f784Smrg    if (pScrn->bitsPerPixel > 8) {
17217104f784Smrg	VisualPtr visual;
17227104f784Smrg	/* Fixup RGB ordering */
17237104f784Smrg	visual = pScreen->visuals + pScreen->numVisuals;
17247104f784Smrg	while (--visual >= pScreen->visuals) {
17257104f784Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
17267104f784Smrg		visual->offsetRed   = pScrn->offset.red;
17277104f784Smrg		visual->offsetGreen = pScrn->offset.green;
17287104f784Smrg		visual->offsetBlue  = pScrn->offset.blue;
17297104f784Smrg		visual->redMask     = pScrn->mask.red;
17307104f784Smrg		visual->greenMask   = pScrn->mask.green;
17317104f784Smrg		visual->blueMask    = pScrn->mask.blue;
17327104f784Smrg	    }
173309885543Smrg	}
173409885543Smrg    }
173509885543Smrg
17367104f784Smrg    /* must be after RGB ordering fixed */
17377104f784Smrg    fbPictureInit(pScreen, 0, 0);
17387104f784Smrg
17397104f784Smrg    /* Do the CRTC independent initialization */
17407104f784Smrg    if(!SMI_HWInit(pScrn))
17417104f784Smrg	LEAVE(FALSE);
174209885543Smrg
17437104f784Smrg    /* Unless using EXA, regardless or using XAA or not, needs offscreen
17447104f784Smrg     * management at least for video. */
17457104f784Smrg    if (pSmi->NoAccel || !pSmi->useEXA) {
17467104f784Smrg	int		numLines;
17477104f784Smrg	BoxRec		AvailFBArea;
174809885543Smrg
17497104f784Smrg	numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
17507104f784Smrg	AvailFBArea.x1 = 0;
17517104f784Smrg	AvailFBArea.y1 = 0;
17527104f784Smrg	AvailFBArea.x2 = pScrn->virtualX;
17537104f784Smrg	AvailFBArea.y2 = numLines;
175409885543Smrg
17557104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
17567104f784Smrg		   "FrameBuffer Box: %d,%d - %d,%d\n",
17577104f784Smrg		   AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
17587104f784Smrg		   AvailFBArea.y2);
175909885543Smrg
17607104f784Smrg	xf86InitFBManager(pScreen, &AvailFBArea);
176109885543Smrg    }
176209885543Smrg
17637104f784Smrg    /* Initialize acceleration layer */
17647104f784Smrg    if (!pSmi->NoAccel) {
17657104f784Smrg	if (pSmi->useEXA && !SMI_EXAInit(pScreen))
17667104f784Smrg	    LEAVE(FALSE);
17677104f784Smrg	else if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
17687104f784Smrg	    LEAVE(FALSE);
176909885543Smrg    }
177009885543Smrg
17717104f784Smrg    /* Initialize the chosen modes */
17727104f784Smrg    if (!xf86SetDesiredModes(pScrn))
17737104f784Smrg	    LEAVE(FALSE);
177409885543Smrg
17757104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
17767104f784Smrg		   "Done writing mode.  Register dump:\n");
17777104f784Smrg    SMI_PrintRegs(pScrn);
177809885543Smrg
17797104f784Smrg    miInitializeBackingStore(pScreen);
178009885543Smrg
17817104f784Smrg#ifdef HAVE_XMODES
17827104f784Smrg    xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
17837104f784Smrg#endif
178409885543Smrg
17857104f784Smrg    /* Initialise cursor functions */
17867104f784Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
178709885543Smrg
17887104f784Smrg    /* Initialize HW cursor layer.  Must follow software cursor
17897104f784Smrg     * initialization.
17907104f784Smrg     */
17917104f784Smrg    if (pSmi->HwCursor) {
17927104f784Smrg	int	size, flags;
17937104f784Smrg
17947104f784Smrg	if (IS_MSOC(pSmi)) {
17957104f784Smrg	    size = SMI501_MAX_CURSOR;
17967104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
17977104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
17987104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
17997104f784Smrg	    if (!pSmi->Dualhead)
18007104f784Smrg		flags |= HARDWARE_CURSOR_ARGB;
18017104f784Smrg#endif
18027104f784Smrg	}
18037104f784Smrg	else {
18047104f784Smrg	    size = SMILYNX_MAX_CURSOR;
18057104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
18067104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
18077104f784Smrg		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
18087104f784Smrg		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
18097104f784Smrg		     HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
18107104f784Smrg		     HARDWARE_CURSOR_INVERT_MASK);
18117104f784Smrg	}
181209885543Smrg
18137104f784Smrg	if (!xf86_cursors_init(pScreen, size, size, flags))
18147104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
18157104f784Smrg		       "Hardware cursor initialization failed\n");
181609885543Smrg    }
181709885543Smrg
18187104f784Smrg    /* Initialise default colormap */
18197104f784Smrg    if (!miCreateDefColormap(pScreen))
18207104f784Smrg	LEAVE(FALSE);
182109885543Smrg
18227104f784Smrg    /* Initialize colormap layer.  Must follow initialization of the default
18237104f784Smrg     * colormap.  And SetGamma call, else it will load palette with solid white.
18247104f784Smrg     */
18257104f784Smrg    if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
18267104f784Smrg			     CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
18277104f784Smrg	LEAVE(FALSE);
182809885543Smrg
18297104f784Smrg    pScreen->SaveScreen = SMI_SaveScreen;
18307104f784Smrg    pSmi->CloseScreen = pScreen->CloseScreen;
18317104f784Smrg    pScreen->CloseScreen = SMI_CloseScreen;
183209885543Smrg
18337104f784Smrg    if ((IS_MSOC(pSmi) &&
18347104f784Smrg	 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
18357104f784Smrg	(!IS_MSOC(pSmi) &&
18367104f784Smrg	 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
18377104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
183809885543Smrg
18397104f784Smrg    SMI_InitVideo(pScreen);
184009885543Smrg
18417104f784Smrg    if(!xf86CrtcScreenInit(pScreen))
18427104f784Smrg	LEAVE(FALSE);
184309885543Smrg
18447104f784Smrg    /* Report any unused options (only for the first generation) */
18457104f784Smrg    if (serverGeneration == 1) {
18467104f784Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
18477104f784Smrg    }
184809885543Smrg
18497104f784Smrg    LEAVE(TRUE);
185009885543Smrg}
185109885543Smrg
185209885543Smrg/*
185309885543Smrg * This is called at the end of each server generation.  It restores the
185409885543Smrg * original (text) mode.  It should also unmap the video memory, and free any
185509885543Smrg * per-generation data allocated by the driver.  It should finish by unwrapping
185609885543Smrg * and calling the saved CloseScreen function.
185709885543Smrg */
185809885543Smrg
185909885543Smrgstatic Bool
186009885543SmrgSMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
186109885543Smrg{
18627104f784Smrg    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
18637104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
18647104f784Smrg    Bool	ret;
186509885543Smrg
18667104f784Smrg    ENTER();
186709885543Smrg
18687104f784Smrg    if (pSmi->HwCursor)
18697104f784Smrg	xf86_cursors_fini(pScreen);
18707104f784Smrg
18717104f784Smrg    if (pScrn->vtSema)
18727104f784Smrg	/* Restore console mode and unmap framebuffer */
18737104f784Smrg	SMI_LeaveVT(scrnIndex, 0);
187409885543Smrg
187509885543Smrg    if (pSmi->XAAInfoRec != NULL) {
187609885543Smrg	XAADestroyInfoRec(pSmi->XAAInfoRec);
187709885543Smrg    }
187809885543Smrg    if (pSmi->EXADriverPtr) {
187909885543Smrg	exaDriverFini(pScreen);
188009885543Smrg	pSmi->EXADriverPtr = NULL;
188109885543Smrg    }
18827104f784Smrg    if (pSmi->pVbe != NULL) {
18837104f784Smrg	vbeFree(pSmi->pVbe);
18847104f784Smrg	pSmi->pVbe = NULL;
188509885543Smrg    }
188609885543Smrg    if (pSmi->pInt10 != NULL) {
188709885543Smrg	xf86FreeInt10(pSmi->pInt10);
188809885543Smrg	pSmi->pInt10 = NULL;
188909885543Smrg    }
189009885543Smrg    if (pSmi->ptrAdaptor != NULL) {
189109885543Smrg	xfree(pSmi->ptrAdaptor);
189209885543Smrg    }
189309885543Smrg    if (pSmi->BlockHandler != NULL) {
189409885543Smrg	pScreen->BlockHandler = pSmi->BlockHandler;
189509885543Smrg    }
189609885543Smrg
189709885543Smrg    pScrn->vtSema = FALSE;
189809885543Smrg    pScreen->CloseScreen = pSmi->CloseScreen;
189909885543Smrg    ret = (*pScreen->CloseScreen)(scrnIndex, pScreen);
190009885543Smrg
19017104f784Smrg    LEAVE(ret);
190209885543Smrg}
190309885543Smrg
190409885543Smrgstatic void
190509885543SmrgSMI_FreeScreen(int scrnIndex, int flags)
190609885543Smrg{
190709885543Smrg    SMI_FreeRec(xf86Screens[scrnIndex]);
190809885543Smrg}
190909885543Smrg
191009885543Smrgstatic Bool
191109885543SmrgSMI_SaveScreen(ScreenPtr pScreen, int mode)
191209885543Smrg{
19137104f784Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
191409885543Smrg
19157104f784Smrg    ENTER();
191609885543Smrg
19177104f784Smrg    if(xf86IsUnblank(mode)){
19187104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
19197104f784Smrg    }else{
19207104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
19217104f784Smrg    }
192209885543Smrg
19237104f784Smrg    LEAVE(TRUE);
192409885543Smrg}
192509885543Smrg
192609885543Smrgvoid
192709885543SmrgSMI_AdjustFrame(int scrnIndex, int x, int y, int flags)
192809885543Smrg{
19297104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(xf86Screens[scrnIndex]);
19307104f784Smrg    xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
193109885543Smrg
19327104f784Smrg    ENTER();
193309885543Smrg
19347104f784Smrg    SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
193509885543Smrg
19367104f784Smrg    LEAVE();
193709885543Smrg}
193809885543Smrg
193909885543SmrgBool
194009885543SmrgSMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
194109885543Smrg{
194209885543Smrg    Bool ret;
19437104f784Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
19447104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
19457104f784Smrg
19467104f784Smrg    ENTER();
194709885543Smrg
19487104f784Smrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
194909885543Smrg
19507104f784Smrg    if (!pSmi->NoAccel)
19517104f784Smrg	SMI_EngineReset(pScrn);
195209885543Smrg
19537104f784Smrg    LEAVE(ret);
195409885543Smrg}
195509885543Smrg
195609885543Smrgvoid
19577104f784SmrgSMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
19587104f784Smrg		LOCO *colors, VisualPtr pVisual)
195909885543Smrg{
19607104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
19617104f784Smrg    int crtc_idx,i,j;
19627104f784Smrg
19637104f784Smrg    ENTER();
19647104f784Smrg
19657104f784Smrg    if(pScrn->bitsPerPixel == 16){
19667104f784Smrg	/* Expand the RGB 565 palette into the 256-elements LUT */
196709885543Smrg
19687104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19697104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
197009885543Smrg
19717104f784Smrg	    for(i=0; i<numColors; i++){
19727104f784Smrg		int idx = indicies[i];
197309885543Smrg
19747104f784Smrg		if(idx<32){
19757104f784Smrg		    for(j=0; j<8; j++){
19767104f784Smrg			crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
19777104f784Smrg			crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
19787104f784Smrg		    }
19797104f784Smrg		}
19807104f784Smrg
19817104f784Smrg		for(j=0; j<4; j++)
19827104f784Smrg		    crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
19837104f784Smrg	    }
19847104f784Smrg
19857104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
198609885543Smrg    }
19877104f784Smrg    }else{
19887104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19897104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
199009885543Smrg
199109885543Smrg    for(i = 0; i < numColors; i++) {
19927104f784Smrg		int idx = indicies[i];
19937104f784Smrg
19947104f784Smrg		crtcPriv->lut_r[idx] = colors[idx].red << 8;
19957104f784Smrg		crtcPriv->lut_g[idx] = colors[idx].green << 8;
19967104f784Smrg		crtcPriv->lut_b[idx] = colors[idx].blue << 8;
19977104f784Smrg	    }
19987104f784Smrg
19997104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
20007104f784Smrg	}
200109885543Smrg    }
200209885543Smrg
20037104f784Smrg    LEAVE();
200409885543Smrg}
200509885543Smrg
200609885543Smrgstatic void
200709885543SmrgSMI_DisableVideo(ScrnInfoPtr pScrn)
200809885543Smrg{
200909885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
201009885543Smrg    CARD8 tmp;
201109885543Smrg
20127104f784Smrg    if (!IS_MSOC(pSmi)) {
20137104f784Smrg	if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
20147104f784Smrg	    return;
20157104f784Smrg	pSmi->DACmask = tmp;
20167104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, 0);
20177104f784Smrg    }
201809885543Smrg}
201909885543Smrg
202009885543Smrgstatic void
202109885543SmrgSMI_EnableVideo(ScrnInfoPtr pScrn)
202209885543Smrg{
202309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
202409885543Smrg
20257104f784Smrg    if (!IS_MSOC(pSmi)) {
20267104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
20277104f784Smrg    }
202809885543Smrg}
202909885543Smrg
203009885543Smrg
203109885543Smrgvoid
203209885543SmrgSMI_EnableMmio(ScrnInfoPtr pScrn)
203309885543Smrg{
203409885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
203509885543Smrg
20367104f784Smrg    ENTER();
203709885543Smrg
20387104f784Smrg    if (!IS_MSOC(pSmi)) {
20397104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
20407104f784Smrg	CARD8 tmp;
20417104f784Smrg
20427104f784Smrg	/*
20437104f784Smrg	 * Enable chipset (seen on uninitialized secondary cards) might not be
20447104f784Smrg	 * needed once we use the VGA softbooter
20457104f784Smrg	 */
20467104f784Smrg	vgaHWSetStdFuncs(hwp);
204709885543Smrg
20487104f784Smrg	/* Enable linear mode */
20497104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20507104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20517104f784Smrg	pSmi->SR18Value = tmp;					/* PDR#521 */
20527104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11);
205309885543Smrg
20547104f784Smrg	/* Enable 2D/3D Engine and Video Processor */
20557104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20567104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20577104f784Smrg	pSmi->SR21Value = tmp;					/* PDR#521 */
20587104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03);
20597104f784Smrg    }
206009885543Smrg
20617104f784Smrg    LEAVE();
206209885543Smrg}
206309885543Smrg
206409885543Smrgvoid
206509885543SmrgSMI_DisableMmio(ScrnInfoPtr pScrn)
206609885543Smrg{
206709885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
206809885543Smrg
20697104f784Smrg    ENTER();
207009885543Smrg
20717104f784Smrg    if (!IS_MSOC(pSmi)) {
20727104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
207309885543Smrg
20747104f784Smrg	vgaHWSetStdFuncs(hwp);
207509885543Smrg
20767104f784Smrg	/* Disable 2D/3D Engine and Video Processor */
20777104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20787104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value);	/* PDR#521 */
20797104f784Smrg
20807104f784Smrg	/* Disable linear mode */
20817104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20827104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value);	/* PDR#521 */
20837104f784Smrg    }
208409885543Smrg
20857104f784Smrg    LEAVE();
208609885543Smrg}
208709885543Smrg
208809885543Smrgstatic void
20897104f784SmrgSMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
20907104f784Smrg{
20917104f784Smrg    vbeInfoPtr pVbe;
20927104f784Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
20937104f784Smrg	pVbe = VBEInit(NULL, index);
20947104f784Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
20957104f784Smrg	vbeFree(pVbe);
20967104f784Smrg    }
20977104f784Smrg}
20987104f784Smrg
20997104f784Smrgstatic Bool
21007104f784SmrgSMI_HWInit(ScrnInfoPtr pScrn)
210109885543Smrg{
210209885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
210309885543Smrg
21047104f784Smrg    ENTER();
210509885543Smrg
21067104f784Smrg    if(IS_MSOC(pSmi))
21077104f784Smrg	LEAVE(SMI501_HWInit(pScrn));
21087104f784Smrg    else
21097104f784Smrg	LEAVE(SMILynx_HWInit(pScrn));
21107104f784Smrg}
211109885543Smrg
21127104f784Smrgvoid
21137104f784SmrgSMI_PrintRegs(ScrnInfoPtr pScrn)
21147104f784Smrg{
21157104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
21167104f784Smrg    int i;
211709885543Smrg
21187104f784Smrg    ENTER();
211909885543Smrg
21207104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
21217104f784Smrg		"START register dump ------------------\n");
21227104f784Smrg
21237104f784Smrg    if(IS_MSOC(pSmi))
21247104f784Smrg	SMI501_PrintRegs(pScrn);
21257104f784Smrg    else
21267104f784Smrg	SMILynx_PrintRegs(pScrn);
212709885543Smrg
212809885543Smrg
212909885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nDPR    x0       x4       x8       xC");
213009885543Smrg    for (i = 0x00; i <= 0x44; i += 4) {
213109885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
213209885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i));
213309885543Smrg    }
213409885543Smrg
213509885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nVPR    x0       x4       x8       xC");
213609885543Smrg    for (i = 0x00; i <= 0x60; i += 4) {
213709885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
213809885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i));
213909885543Smrg    }
214009885543Smrg
214109885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nCPR    x0       x4       x8       xC");
214209885543Smrg    for (i = 0x00; i <= 0x18; i += 4) {
214309885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
214409885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i));
214509885543Smrg    }
214609885543Smrg
214709885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\n");
214809885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
214909885543Smrg		"END register dump --------------------\n");
215009885543Smrg
21517104f784Smrg    LEAVE();
215209885543Smrg}
2153