smi_driver.c revision b698ba48
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
34b698ba48Smrg#include "xf86.h"
3509885543Smrg#include "xf86DDC.h"
3609885543Smrg#include "xf86int10.h"
3709885543Smrg#include "vbe.h"
3809885543Smrg
39b698ba48Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
40b698ba48Smrg#include "xf86Resources.h"
41b698ba48Smrg#include "xf86RAC.h"
42b698ba48Smrg#endif
43b698ba48Smrg
4409885543Smrg#include "smi.h"
457104f784Smrg#include "smi_501.h"
467104f784Smrg#include "smilynx.h"
477104f784Smrg#include "smi_crtc.h"
4809885543Smrg
4909885543Smrg#include "globals.h"
50b698ba48Smrg#ifdef HAVE_XEXTPROTO_71
51b698ba48Smrg#include <X11/extensions/dpmsconst.h>
52b698ba48Smrg#else
5309885543Smrg#define DPMS_SERVER
5409885543Smrg#include <X11/extensions/dpms.h>
55b698ba48Smrg#endif
56b698ba48Smrg
5709885543Smrg
5809885543Smrg/*
5909885543Smrg * Internals
6009885543Smrg */
617104f784Smrgstatic Bool SMI_MapMmio(ScrnInfoPtr pScrn);
627104f784Smrgstatic Bool SMI_DetectMem(ScrnInfoPtr pScrn);
6309885543Smrgstatic void SMI_EnableMmio(ScrnInfoPtr pScrn);
6409885543Smrgstatic void SMI_DisableMmio(ScrnInfoPtr pScrn);
657104f784Smrgstatic Bool SMI_HWInit(ScrnInfoPtr pScrn);
6609885543Smrg
6709885543Smrg/*
6809885543Smrg * Forward definitions for the functions that make up the driver.
6909885543Smrg */
7009885543Smrg
7109885543Smrgstatic const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid);
7209885543Smrgstatic void SMI_Identify(int flags);
7309885543Smrgstatic Bool SMI_Probe(DriverPtr drv, int flags);
7409885543Smrgstatic Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
7509885543Smrgstatic Bool SMI_EnterVT(int scrnIndex, int flags);
7609885543Smrgstatic void SMI_LeaveVT(int scrnIndex, int flags);
7709885543Smrgstatic Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
7809885543Smrg                           char **argv);
7909885543Smrgstatic void SMI_DisableVideo(ScrnInfoPtr pScrn);
8009885543Smrgstatic void SMI_EnableVideo(ScrnInfoPtr pScrn);
8109885543Smrgstatic Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen);
8209885543Smrgstatic Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
8309885543Smrgstatic void SMI_FreeScreen(int ScrnIndex, int flags);
8409885543Smrgstatic void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
8509885543Smrgstatic void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
867104f784Smrgstatic void SMI_DetectMCLK(ScrnInfoPtr pScrn);
8709885543Smrg
887104f784Smrg/*
897104f784Smrg * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
907104f784Smrg * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion"
917104f784Smrg */
927104f784Smrg#define SILICONMOTION_NAME          "SMI"
9309885543Smrg#define SILICONMOTION_DRIVER_NAME   "siliconmotion"
947104f784Smrg#define SILICONMOTION_VERSION_NAME  PACKAGE_VERSION
957104f784Smrg#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR
967104f784Smrg#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR
977104f784Smrg#define SILICONMOTION_PATCHLEVEL    PACKAGE_VERSION_PATCHLEVEL
9809885543Smrg#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
9909885543Smrg                                      (SILICONMOTION_VERSION_MINOR << 16) | \
10009885543Smrg                                      (SILICONMOTION_PATCHLEVEL))
10109885543Smrg
1027104f784Smrg#if SMI_DEBUG
1037104f784Smrgint smi_indent = 1;
1047104f784Smrg#endif
1057104f784Smrg
1067104f784Smrg/* for dualhead */
1077104f784Smrgint gSMIEntityIndex = -1;
1087104f784Smrg
10909885543Smrg/*
11009885543Smrg * This contains the functions needed by the server after loading the
11109885543Smrg * driver module.  It must be supplied, and gets added the driver list by
11209885543Smrg * the Module Setup funtion in the dynamic case.  In the static case a
11309885543Smrg * reference to this is compiled in, and this requires that the name of
11409885543Smrg * this DriverRec be an upper-case version of the driver name.
11509885543Smrg */
11609885543Smrg
11709885543Smrg_X_EXPORT DriverRec SILICONMOTION =
11809885543Smrg{
11909885543Smrg    SILICONMOTION_DRIVER_VERSION,
12009885543Smrg    SILICONMOTION_DRIVER_NAME,
12109885543Smrg    SMI_Identify,
12209885543Smrg    SMI_Probe,
12309885543Smrg    SMI_AvailableOptions,
12409885543Smrg    NULL,
12509885543Smrg    0
12609885543Smrg};
12709885543Smrg
12809885543Smrg/* Supported chipsets */
12909885543Smrgstatic SymTabRec SMIChipsets[] =
13009885543Smrg{
13109885543Smrg    { PCI_CHIP_SMI910, "Lynx"    },
13209885543Smrg    { PCI_CHIP_SMI810, "LynxE"   },
13309885543Smrg    { PCI_CHIP_SMI820, "Lynx3D"  },
13409885543Smrg    { PCI_CHIP_SMI710, "LynxEM"  },
13509885543Smrg    { PCI_CHIP_SMI712, "LynxEM+" },
13609885543Smrg    { PCI_CHIP_SMI720, "Lynx3DM" },
13709885543Smrg    { PCI_CHIP_SMI731, "Cougar3DR" },
1387104f784Smrg    { PCI_CHIP_SMI501, "MSOC"	 },
13909885543Smrg    { -1,             NULL      }
14009885543Smrg};
14109885543Smrg
14209885543Smrgstatic PciChipsets SMIPciChipsets[] =
14309885543Smrg{
1447104f784Smrg    /* numChipset,	PciID,			Resource */
14509885543Smrg    { PCI_CHIP_SMI910,	PCI_CHIP_SMI910,	RES_SHARED_VGA },
14609885543Smrg    { PCI_CHIP_SMI810,	PCI_CHIP_SMI810,	RES_SHARED_VGA },
14709885543Smrg    { PCI_CHIP_SMI820,	PCI_CHIP_SMI820,	RES_SHARED_VGA },
14809885543Smrg    { PCI_CHIP_SMI710,	PCI_CHIP_SMI710,	RES_SHARED_VGA },
14909885543Smrg    { PCI_CHIP_SMI712,	PCI_CHIP_SMI712,	RES_SHARED_VGA },
15009885543Smrg    { PCI_CHIP_SMI720,	PCI_CHIP_SMI720,	RES_SHARED_VGA },
15109885543Smrg    { PCI_CHIP_SMI731,	PCI_CHIP_SMI731,	RES_SHARED_VGA },
1527104f784Smrg    { PCI_CHIP_SMI501,	PCI_CHIP_SMI501,	RES_UNDEFINED  },
1537104f784Smrg    { -1,		-1,			RES_UNDEFINED  }
15409885543Smrg};
15509885543Smrg
15609885543Smrgtypedef enum
15709885543Smrg{
15809885543Smrg    OPTION_PCI_BURST,
15909885543Smrg    OPTION_PCI_RETRY,
16009885543Smrg    OPTION_NOACCEL,
16109885543Smrg    OPTION_MCLK,
1627104f784Smrg    OPTION_MXCLK,
16309885543Smrg    OPTION_SWCURSOR,
16409885543Smrg    OPTION_HWCURSOR,
16509885543Smrg    OPTION_VIDEOKEY,
16609885543Smrg    OPTION_BYTESWAP,
16709885543Smrg    /* CZ 26.10.2001: interlaced video */
16809885543Smrg    OPTION_INTERLACED,
16909885543Smrg    /* end CZ */
17009885543Smrg    OPTION_USEBIOS,
17109885543Smrg    OPTION_DUALHEAD,
17209885543Smrg    OPTION_ACCELMETHOD,
1737104f784Smrg    OPTION_PANEL_SIZE,
1747104f784Smrg    OPTION_USE_FBDEV,
1757104f784Smrg    OPTION_CSCVIDEO,
17609885543Smrg    NUMBER_OF_OPTIONS
17709885543Smrg} SMIOpts;
17809885543Smrg
17909885543Smrgstatic const OptionInfoRec SMIOptions[] =
18009885543Smrg{
1817104f784Smrg    { OPTION_PCI_BURST,	     "pci_burst",	  OPTV_BOOLEAN, {0}, TRUE },
1827104f784Smrg    { OPTION_PCI_RETRY,	     "pci_retry",	  OPTV_BOOLEAN, {0}, TRUE },
18309885543Smrg    { OPTION_NOACCEL,	     "NoAccel",		  OPTV_BOOLEAN, {0}, FALSE },
1847104f784Smrg    { OPTION_MCLK,	     "MCLK",		  OPTV_FREQ,	{0}, FALSE },
1857104f784Smrg    { OPTION_MXCLK,	     "MXCLK",		  OPTV_FREQ,	{0}, FALSE },
1867104f784Smrg    { OPTION_HWCURSOR,	     "HWCursor",	  OPTV_BOOLEAN, {0}, TRUE },
18709885543Smrg    { OPTION_SWCURSOR,	     "SWCursor",	  OPTV_BOOLEAN, {0}, FALSE },
18809885543Smrg    { OPTION_VIDEOKEY,	     "VideoKey",	  OPTV_INTEGER, {0}, FALSE },
18909885543Smrg    { OPTION_BYTESWAP,	     "ByteSwap",	  OPTV_BOOLEAN, {0}, FALSE },
19009885543Smrg    /* CZ 26.10.2001: interlaced video */
1917104f784Smrg    { OPTION_INTERLACED,     "Interlaced",        OPTV_BOOLEAN, {0}, FALSE },
19209885543Smrg    /* end CZ */
19309885543Smrg    { OPTION_USEBIOS,	     "UseBIOS",		  OPTV_BOOLEAN,	{0}, FALSE },
1947104f784Smrg    { OPTION_DUALHEAD,	     "Dualhead",	  OPTV_BOOLEAN,	{0}, TRUE },
19509885543Smrg    { OPTION_ACCELMETHOD,    "AccelMethod",       OPTV_STRING,  {0}, FALSE },
1967104f784Smrg    { OPTION_PANEL_SIZE,     "PanelSize",	  OPTV_ANYSTR,	{0}, FALSE },
1977104f784Smrg    { OPTION_USE_FBDEV,	     "UseFBDev",	  OPTV_BOOLEAN,	{0}, FALSE },
1987104f784Smrg    { OPTION_CSCVIDEO,	     "CSCVideo",	  OPTV_BOOLEAN, {0}, TRUE },
19909885543Smrg    { -1,		     NULL,		  OPTV_NONE,	{0}, FALSE }
20009885543Smrg};
20109885543Smrg
20209885543Smrg#ifdef XFree86LOADER
20309885543Smrg
20409885543Smrgstatic MODULESETUPPROTO(siliconmotionSetup);
20509885543Smrg
20609885543Smrgstatic XF86ModuleVersionInfo SMIVersRec =
20709885543Smrg{
20809885543Smrg    "siliconmotion",
20909885543Smrg    MODULEVENDORSTRING,
21009885543Smrg    MODINFOSTRING1,
21109885543Smrg    MODINFOSTRING2,
21209885543Smrg    XORG_VERSION_CURRENT,
21309885543Smrg    SILICONMOTION_VERSION_MAJOR,
21409885543Smrg    SILICONMOTION_VERSION_MINOR,
21509885543Smrg    SILICONMOTION_PATCHLEVEL,
21609885543Smrg    ABI_CLASS_VIDEODRV,
21709885543Smrg    ABI_VIDEODRV_VERSION,
21809885543Smrg    MOD_CLASS_VIDEODRV,
21909885543Smrg    {0, 0, 0, 0}
22009885543Smrg};
22109885543Smrg
22209885543Smrg/*
22309885543Smrg * This is the module init data for XFree86 modules.
22409885543Smrg *
22509885543Smrg * Its name has to be the driver name followed by ModuleData.
22609885543Smrg */
22709885543Smrg_X_EXPORT XF86ModuleData siliconmotionModuleData =
22809885543Smrg{
22909885543Smrg    &SMIVersRec,
23009885543Smrg    siliconmotionSetup,
23109885543Smrg    NULL
23209885543Smrg};
23309885543Smrg
23409885543Smrgstatic pointer
23509885543SmrgsiliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin)
23609885543Smrg{
23709885543Smrg    static Bool setupDone = FALSE;
23809885543Smrg
23909885543Smrg    if (!setupDone) {
24009885543Smrg	setupDone = TRUE;
24109885543Smrg	xf86AddDriver(&SILICONMOTION, module, 0);
24209885543Smrg
24309885543Smrg	/*
24409885543Smrg	 * The return value must be non-NULL on success even though there
24509885543Smrg	 * is no TearDownProc.
24609885543Smrg	 */
24709885543Smrg	return (pointer) 1;
24809885543Smrg
24909885543Smrg    } else {
25009885543Smrg	if (errmaj) {
25109885543Smrg	    *errmaj = LDR_ONCEONLY;
25209885543Smrg	}
25309885543Smrg	return NULL;
25409885543Smrg    }
25509885543Smrg}
25609885543Smrg
25709885543Smrg#endif /* XFree86LOADER */
25809885543Smrg
25909885543Smrgstatic Bool
26009885543SmrgSMI_GetRec(ScrnInfoPtr pScrn)
26109885543Smrg{
2627104f784Smrg    ENTER();
26309885543Smrg
26409885543Smrg    /*
26509885543Smrg     * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
26609885543Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
26709885543Smrg     * the allocation has already been done.
26809885543Smrg     */
26909885543Smrg    if (pScrn->driverPrivate == NULL) {
27009885543Smrg	pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
27109885543Smrg    }
27209885543Smrg
2737104f784Smrg    LEAVE(TRUE);
27409885543Smrg}
27509885543Smrg
27609885543Smrgstatic void
27709885543SmrgSMI_FreeRec(ScrnInfoPtr pScrn)
27809885543Smrg{
2797104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
28009885543Smrg
2817104f784Smrg    ENTER();
2827104f784Smrg
2837104f784Smrg    if (pSmi) {
2847104f784Smrg	xfree(pSmi->save);
2857104f784Smrg	xfree(pSmi->mode);
28609885543Smrg	xfree(pScrn->driverPrivate);
28709885543Smrg	pScrn->driverPrivate = NULL;
28809885543Smrg    }
28909885543Smrg
2907104f784Smrg    LEAVE();
29109885543Smrg}
29209885543Smrg
29309885543Smrgstatic const OptionInfoRec *
29409885543SmrgSMI_AvailableOptions(int chipid, int busid)
29509885543Smrg{
2967104f784Smrg    ENTER();
2977104f784Smrg
2987104f784Smrg    LEAVE(SMIOptions);
29909885543Smrg}
30009885543Smrg
30109885543Smrgstatic void
30209885543SmrgSMI_Identify(int flags)
30309885543Smrg{
3047104f784Smrg    ENTER();
30509885543Smrg
30609885543Smrg    xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
30709885543Smrg		SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
30809885543Smrg		SMIChipsets);
30909885543Smrg
3107104f784Smrg    LEAVE();
31109885543Smrg}
31209885543Smrg
31309885543Smrgstatic Bool
31409885543SmrgSMI_Probe(DriverPtr drv, int flags)
31509885543Smrg{
31609885543Smrg    int i;
31709885543Smrg    GDevPtr *devSections;
31809885543Smrg    int *usedChips;
31909885543Smrg    int numDevSections;
32009885543Smrg    int numUsed;
32109885543Smrg    Bool foundScreen = FALSE;
32209885543Smrg
3237104f784Smrg    ENTER();
32409885543Smrg
32509885543Smrg    numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
32609885543Smrg
3277104f784Smrg    if (numDevSections <= 0)
32809885543Smrg	/* There's no matching device section in the config file, so quit now. */
3297104f784Smrg	LEAVE(FALSE);
33009885543Smrg
3317104f784Smrg#ifndef XSERVER_LIBPCIACCESS
3327104f784Smrg    if (xf86GetPciVideoInfo() == NULL)
3337104f784Smrg	LEAVE(FALSE);
3347104f784Smrg#endif
33509885543Smrg
33609885543Smrg    numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
33709885543Smrg				    SMIChipsets, SMIPciChipsets, devSections,
33809885543Smrg				    numDevSections, drv, &usedChips);
33909885543Smrg
34009885543Smrg    /* Free it since we don't need that list after this */
34109885543Smrg    xfree(devSections);
3427104f784Smrg    if (numUsed <= 0)
3437104f784Smrg	LEAVE(FALSE);
3447104f784Smrg
3457104f784Smrg    if (flags & PROBE_DETECT)
3467104f784Smrg	foundScreen = TRUE;
3477104f784Smrg    else {
3487104f784Smrg	ScrnInfoPtr	pScrn;
3497104f784Smrg	EntityInfoPtr	pEnt;
35009885543Smrg
35109885543Smrg	for (i = 0; i < numUsed; i++) {
3527104f784Smrg	    if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
3537104f784Smrg					     SMIPciChipsets, NULL,
3547104f784Smrg					     NULL, NULL, NULL, NULL))) {
3557104f784Smrg		pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
3567104f784Smrg		pScrn->driverName    = SILICONMOTION_DRIVER_NAME;
3577104f784Smrg		pScrn->name	     = SILICONMOTION_NAME;
3587104f784Smrg		pScrn->Probe	     = SMI_Probe;
3597104f784Smrg		pScrn->PreInit	     = SMI_PreInit;
3607104f784Smrg		pScrn->ScreenInit    = SMI_ScreenInit;
3617104f784Smrg		pScrn->SwitchMode    = SMI_SwitchMode;
3627104f784Smrg		pScrn->AdjustFrame   = SMI_AdjustFrame;
3637104f784Smrg
3647104f784Smrg		if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
3657104f784Smrg			pScrn->EnterVT   = SMI_EnterVT;
3667104f784Smrg			pScrn->LeaveVT   = SMI_LeaveVT;
3677104f784Smrg		    xfree(pEnt);
3687104f784Smrg		}
3697104f784Smrg		pScrn->FreeScreen    = SMI_FreeScreen;
3707104f784Smrg		foundScreen	     = TRUE;
3717104f784Smrg	    }
37209885543Smrg	}
37309885543Smrg    }
37409885543Smrg    xfree(usedChips);
37509885543Smrg
3767104f784Smrg    LEAVE(foundScreen);
37709885543Smrg}
37809885543Smrg
37909885543Smrgstatic Bool
38009885543SmrgSMI_PreInit(ScrnInfoPtr pScrn, int flags)
38109885543Smrg{
38209885543Smrg    EntityInfoPtr pEnt;
38309885543Smrg    SMIPtr pSmi;
38409885543Smrg    MessageType from;
38509885543Smrg    vgaHWPtr hwp;
38609885543Smrg
3877104f784Smrg    ENTER();
38809885543Smrg
38909885543Smrg    /* Ignoring the Type list for now.  It might be needed when multiple cards
39009885543Smrg     * are supported.
39109885543Smrg     */
3927104f784Smrg    if (pScrn->numEntities > 1)
3937104f784Smrg	LEAVE(FALSE);
39409885543Smrg
3957104f784Smrg    /* Allocate the SMIRec driverPrivate */
3967104f784Smrg    if (!SMI_GetRec(pScrn))
3977104f784Smrg	LEAVE(FALSE);
3987104f784Smrg    pSmi = SMIPTR(pScrn);
39909885543Smrg
4007104f784Smrg    /* Find the PCI slot for this screen */
4017104f784Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
40209885543Smrg
4037104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
4047104f784Smrg    pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
4057104f784Smrg
4067104f784Smrg    if (IS_MSOC(pSmi)) {
4077104f784Smrg	pSmi->Save = SMI501_Save;
4087104f784Smrg	pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
4097104f784Smrg	pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
4107104f784Smrg    }
4117104f784Smrg    else {
4127104f784Smrg	pSmi->Save = SMILynx_Save;
4137104f784Smrg	pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
4147104f784Smrg	pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
41509885543Smrg    }
41609885543Smrg
4177104f784Smrg    if (flags & PROBE_DETECT) {
4187104f784Smrg	if (!IS_MSOC(pSmi))
4197104f784Smrg	    SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
4207104f784Smrg	LEAVE(TRUE);
42109885543Smrg    }
4227104f784Smrg
423b698ba48Smrg    if (pEnt->location.type != BUS_PCI) {
4247104f784Smrg	xfree(pEnt);
4257104f784Smrg	SMI_FreeRec(pScrn);
4267104f784Smrg	LEAVE(FALSE);
4277104f784Smrg    }
4287104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
42909885543Smrg
43009885543Smrg    /* Set pScrn->monitor */
43109885543Smrg    pScrn->monitor = pScrn->confScreen->monitor;
43209885543Smrg
4337104f784Smrg    if (!IS_MSOC(pSmi)) {
4347104f784Smrg	/* The vgahw module should be loaded here when needed */
4357104f784Smrg	if (!xf86LoadSubModule(pScrn, "vgahw"))
4367104f784Smrg	    LEAVE(FALSE);
4377104f784Smrg
4387104f784Smrg	/*
4397104f784Smrg	 * Allocate a vgaHWRec
4407104f784Smrg	 */
4417104f784Smrg	if (!vgaHWGetHWRec(pScrn))
4427104f784Smrg	    LEAVE(FALSE);
4437104f784Smrg
4447104f784Smrg	hwp = VGAHWPTR(pScrn);
4457104f784Smrg	pSmi->PIOBase = hwp->PIOOffset;
4467104f784Smrg
4477104f784Smrg	xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
4487104f784Smrg		       "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET,
4497104f784Smrg		       hwp->IOBase, hwp->MMIOBase);
4507104f784Smrg    }
4517104f784Smrg
45209885543Smrg    /*
45309885543Smrg     * The first thing we should figure out is the depth, bpp, etc.
45409885543Smrg     */
4557104f784Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
4567104f784Smrg	LEAVE(FALSE);
45709885543Smrg
45809885543Smrg    /* Check that the returned depth is one we support */
4597104f784Smrg    if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) {
46009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
46109885543Smrg		   "Given depth (%d) is not supported by this driver\n",
46209885543Smrg		   pScrn->depth);
4637104f784Smrg	LEAVE(FALSE);
4647104f784Smrg    }
4657104f784Smrg
4667104f784Smrg
4677104f784Smrg    if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
4687104f784Smrg       pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
4697104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4707104f784Smrg		   "Given bpp (%d) is not supported by this driver\n",
4717104f784Smrg		   pScrn->bitsPerPixel);
4727104f784Smrg	LEAVE(FALSE);
47309885543Smrg    }
47409885543Smrg
47509885543Smrg    xf86PrintDepthBpp(pScrn);
47609885543Smrg
4772ec8c4b4Smrg    pSmi->Bpp = pScrn->bitsPerPixel >> 3;
4782ec8c4b4Smrg
47909885543Smrg    /*
48009885543Smrg     * This must happen after pScrn->display has been set because
48109885543Smrg     * xf86SetWeight references it.
48209885543Smrg     */
48309885543Smrg    if (pScrn->depth > 8) {
48409885543Smrg	/* The defaults are OK for us */
48509885543Smrg	rgb zeros = {0, 0, 0};
4867104f784Smrg#if __BYTE_ORDER == __BIG_ENDIAN
4877104f784Smrg	rgb masks = {0xff00,0xff0000,0xff000000};
4887104f784Smrg#else
4897104f784Smrg	rgb masks = {0, 0, 0};
4907104f784Smrg#endif
49109885543Smrg
4927104f784Smrg	if (!xf86SetWeight(pScrn, zeros, masks))
4937104f784Smrg	    LEAVE(FALSE);
49409885543Smrg    }
49509885543Smrg
4967104f784Smrg    if (!xf86SetDefaultVisual(pScrn, -1))
4977104f784Smrg	LEAVE(FALSE);
49809885543Smrg
49909885543Smrg    /* We don't currently support DirectColor at > 8bpp */
5007104f784Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
50109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) "
50209885543Smrg		   "is not supported at depth %d\n",
50309885543Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
5047104f784Smrg	LEAVE(FALSE);
50509885543Smrg    }
50609885543Smrg
50709885543Smrg    /* We use a programmable clock */
50809885543Smrg    pScrn->progClock = TRUE;
50909885543Smrg
51009885543Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
51109885543Smrg    xf86CollectOptions(pScrn, NULL);
51209885543Smrg
51309885543Smrg    /* Set the bits per RGB for 8bpp mode */
5147104f784Smrg    if (pScrn->depth == 8){
5157104f784Smrg	pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
5167104f784Smrg    }else if(pScrn->depth == 16){
5177104f784Smrg	/* Use 8 bit LUT for gamma correction*/
5187104f784Smrg	pScrn->rgbBits = 8;
51909885543Smrg    }
52009885543Smrg
52109885543Smrg    /* Process the options */
52209885543Smrg    if (!(pSmi->Options = xalloc(sizeof(SMIOptions))))
5237104f784Smrg	LEAVE(FALSE);
5247104f784Smrg
52509885543Smrg    memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
52609885543Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
52709885543Smrg
5287104f784Smrg    /* Enable pci burst by default */
5297104f784Smrg    from = X_DEFAULT;
5307104f784Smrg    pSmi->PCIBurst = TRUE;
5317104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst))
5327104f784Smrg	from = X_CONFIG;
5337104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n",
5347104f784Smrg	       pSmi->PCIBurst ? "en" : "dis");
53509885543Smrg
5367104f784Smrg    /* Pci retry enabled by default if pci burst also enabled */
5377104f784Smrg    from = X_DEFAULT;
5387104f784Smrg    pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE;
5397104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) {
5407104f784Smrg	from = X_CONFIG;
5417104f784Smrg	if (pSmi->PCIRetry && !pSmi->PCIBurst) {
5427104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5437104f784Smrg		       "\"pci_retry\" option requires \"pci_burst\".\n");
5447104f784Smrg	    pSmi->PCIRetry = FALSE;
54509885543Smrg	}
54609885543Smrg    }
5477104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n",
5487104f784Smrg	       pSmi->PCIRetry ? "en" : "dis");
54909885543Smrg
55009885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) {
55109885543Smrg	pSmi->NoAccel = TRUE;
55209885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
55309885543Smrg		   "disabled\n");
55409885543Smrg    } else {
55509885543Smrg	pSmi->NoAccel = FALSE;
55609885543Smrg    }
55709885543Smrg
5587104f784Smrg    if (IS_MSOC(pSmi)) {
5597104f784Smrg	from = X_DEFAULT;
5607104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
5617104f784Smrg	    from = X_CONFIG;
5627104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n",
5637104f784Smrg		   pSmi->UseFBDev ? "enabled" : "disabled");
5647104f784Smrg    }
5657104f784Smrg
5667104f784Smrg    from = X_CONFIG;
5677104f784Smrg    pSmi->HwCursor = TRUE;
5687104f784Smrg    /* SWCursor overrides HWCusor if both specified */
5697104f784Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
5707104f784Smrg	pSmi->HwCursor = FALSE;
5717104f784Smrg    else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
5727104f784Smrg	from = X_DEFAULT;
57309885543Smrg
5747104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
5757104f784Smrg	       pSmi->HwCursor ? "Hard" : "Soft");
57609885543Smrg
57709885543Smrg    if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
57809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
57909885543Smrg		   "0x%08X\n", pSmi->videoKey);
58009885543Smrg    } else {
58109885543Smrg	pSmi->videoKey = (1 << pScrn->offset.red) |
58209885543Smrg			 (1 << pScrn->offset.green) |
58309885543Smrg			 (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
58409885543Smrg			 << pScrn->offset.blue);
58509885543Smrg    }
58609885543Smrg
58709885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) {
58809885543Smrg	pSmi->ByteSwap = TRUE;
58909885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
59009885543Smrg    } else {
59109885543Smrg	pSmi->ByteSwap = FALSE;
59209885543Smrg    }
59309885543Smrg
59409885543Smrg    /* CZ 26.10.2001: interlaced video */
59509885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) {
59609885543Smrg	pSmi->interlaced = TRUE;
59709885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
59809885543Smrg    } else {
59909885543Smrg	pSmi->interlaced = FALSE;
60009885543Smrg    }
60109885543Smrg    /* end CZ */
60209885543Smrg
6037104f784Smrg    if (IS_MSOC(pSmi))
6047104f784Smrg	pSmi->useBIOS = FALSE;
6057104f784Smrg    else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) {
60609885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
60709885543Smrg		   pSmi->useBIOS ? "enabled" : "disabled");
6087104f784Smrg    }
6097104f784Smrg    else if(pSmi->Chipset == SMI_LYNX3DM){
6107104f784Smrg	/* Default to UseBIOS disabled. */
6117104f784Smrg	pSmi->useBIOS = FALSE;
6127104f784Smrg    }
6137104f784Smrg    else {
61409885543Smrg	/* Default to UseBIOS enabled. */
61509885543Smrg	pSmi->useBIOS = TRUE;
61609885543Smrg    }
61709885543Smrg
6187104f784Smrg    if (pSmi->useBIOS) {
6197104f784Smrg	if (xf86LoadSubModule(pScrn,"int10")) {
6207104f784Smrg	    pSmi->pInt10 = xf86InitInt10(pEnt->index);
6217104f784Smrg	}
62209885543Smrg
6237104f784Smrg	if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
6247104f784Smrg	    pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
6257104f784Smrg	}
62609885543Smrg
6277104f784Smrg	if(!pSmi->pVbe){
6287104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n");
6297104f784Smrg	    pSmi->useBIOS = FALSE;
6307104f784Smrg	}
63109885543Smrg    }
63209885543Smrg
633b698ba48Smrg#ifndef XSERVER_LIBPCIACCESS
63409885543Smrg    xf86RegisterResources(pEnt->index, NULL, ResExclusive);
635b698ba48Smrg#endif
63609885543Smrg    /*
63709885543Smrg     * Set the Chipset and ChipRev, allowing config file entries to
63809885543Smrg     * override.
63909885543Smrg     */
64009885543Smrg    if (pEnt->device->chipset && *pEnt->device->chipset) {
64109885543Smrg	pScrn->chipset = pEnt->device->chipset;
64209885543Smrg	pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
64309885543Smrg	from = X_CONFIG;
6447104f784Smrg    }
6457104f784Smrg    else if (pEnt->device->chipID >= 0) {
64609885543Smrg	pSmi->Chipset = pEnt->device->chipID;
64709885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
64809885543Smrg	from = X_CONFIG;
64909885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
65009885543Smrg		   pSmi->Chipset);
6517104f784Smrg    }
6527104f784Smrg    else {
65309885543Smrg	from = X_PROBED;
6547104f784Smrg	pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
65509885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
65609885543Smrg    }
65709885543Smrg
65809885543Smrg    if (pEnt->device->chipRev >= 0) {
65909885543Smrg	pSmi->ChipRev = pEnt->device->chipRev;
66009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
66109885543Smrg		   pSmi->ChipRev);
66209885543Smrg    }
6637104f784Smrg    else
6647104f784Smrg        pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo);
66509885543Smrg    xfree(pEnt);
66609885543Smrg
66709885543Smrg    /*
66809885543Smrg     * This shouldn't happen because such problems should be caught in
66909885543Smrg     * SMI_Probe(), but check it just in case.
67009885543Smrg     */
67109885543Smrg    if (pScrn->chipset == NULL) {
67209885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
67309885543Smrg				"recognised\n", pSmi->Chipset);
6747104f784Smrg	LEAVE(FALSE);
67509885543Smrg    }
67609885543Smrg
67709885543Smrg    if (pSmi->Chipset < 0) {
67809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
67909885543Smrg		   "recognised\n", pScrn->chipset);
6807104f784Smrg	LEAVE(FALSE);
68109885543Smrg    }
68209885543Smrg
68309885543Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
68409885543Smrg
6857104f784Smrg#ifndef XSERVER_LIBPCIACCESS
68609885543Smrg    pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
68709885543Smrg		   	  pSmi->PciInfo->func);
6887104f784Smrg#endif
68909885543Smrg
6907104f784Smrg    from = X_DEFAULT;
6917104f784Smrg    if(pSmi->Chipset == SMI_LYNX3DM &&
6927104f784Smrg       pScrn->bitsPerPixel == 16)
69309885543Smrg	pSmi->Dualhead = TRUE;
6947104f784Smrg    else
6957104f784Smrg	pSmi->Dualhead = FALSE;
6967104f784Smrg
6977104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead))
6987104f784Smrg	from = X_CONFIG;
6997104f784Smrg
7007104f784Smrg    if (IS_MSOC(pSmi)) {
7017104f784Smrg	pSmi->lcd = TRUE;
7027104f784Smrg	if (pSmi->Dualhead && pSmi->UseFBDev) {
7037104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7047104f784Smrg		       "Dual head disabled in fbdev mode\n");
7057104f784Smrg	    pSmi->Dualhead = FALSE;
7067104f784Smrg	}
7077104f784Smrg	/* FIXME Randr cursor code only works properly when argb cursors
7087104f784Smrg	 * are also supported.
7097104f784Smrg	 * FIXME This probably is a randr cursor bug, and since access to
7107104f784Smrg	 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor
7117104f784Smrg	 * field is not available, one cannot easily workaround the problem,
7127104f784Smrg	 * so, just disable it...
7137104f784Smrg	 * TODO Check with a X Server newer then 1.4.0.90 (that is being
7147104f784Smrg	 * used in the 502 OEM image).
7157104f784Smrg	 * */
7167104f784Smrg	if (pSmi->Dualhead && pSmi->HwCursor) {
7177104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7187104f784Smrg		       "HW Cursor disabled in dual head mode\n");
7197104f784Smrg	    pSmi->HwCursor = FALSE;
7207104f784Smrg	}
7217104f784Smrg    }
7227104f784Smrg    else if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
7237104f784Smrg	/* tweak options for dualhead */
7247104f784Smrg	if (pSmi->Dualhead) {
7257104f784Smrg	    pSmi->useBIOS = FALSE;
7267104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n");
7277104f784Smrg	    pSmi->HwCursor = FALSE;
7287104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n");
7297104f784Smrg	    if (pScrn->bitsPerPixel != 16) {
7307104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at "
7317104f784Smrg			   "depth 16\n");
7327104f784Smrg		LEAVE(FALSE);
7337104f784Smrg	    }
7347104f784Smrg	}
73509885543Smrg    }
7367104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n",
7377104f784Smrg	       pSmi->Dualhead ? "en" : "dis");
73809885543Smrg
7397104f784Smrg    if (!pSmi->NoAccel) {
7407104f784Smrg	char *strptr;
7417104f784Smrg
7427104f784Smrg	from = X_DEFAULT;
7437104f784Smrg	if ((strptr = (char *)xf86GetOptValString(pSmi->Options,
7447104f784Smrg						  OPTION_ACCELMETHOD))) {
7457104f784Smrg	    if (!xf86NameCmp(strptr,"XAA")) {
7467104f784Smrg		from = X_CONFIG;
7477104f784Smrg		pSmi->useEXA = FALSE;
7487104f784Smrg	    } else if(!xf86NameCmp(strptr,"EXA")) {
7497104f784Smrg		from = X_CONFIG;
7507104f784Smrg		pSmi->useEXA = TRUE;
7517104f784Smrg	    }
75209885543Smrg	}
7537104f784Smrg
7547104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
7557104f784Smrg		pSmi->useEXA ? "EXA" : "XAA");
75609885543Smrg    }
75709885543Smrg
7587104f784Smrg    if (IS_MSOC(pSmi)) {
7597104f784Smrg	pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead;
7607104f784Smrg	from = X_DEFAULT;
7617104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) {
7627104f784Smrg	    from = X_CONFIG;
7637104f784Smrg
7647104f784Smrg	    /* FIXME */
7657104f784Smrg	    if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) {
7667104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
7677104f784Smrg			   "CSCVideo requires XAA or EXA in single head mode.\n");
7687104f784Smrg		pSmi->CSCVideo = FALSE;
7697104f784Smrg	    }
7707104f784Smrg	}
77109885543Smrg
7727104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n",
7737104f784Smrg		   pSmi->CSCVideo ? "en" : "dis");
7747104f784Smrg    }
77509885543Smrg
7767104f784Smrg    SMI_MapMmio(pScrn);
7777104f784Smrg    SMI_DetectMem(pScrn);
7787104f784Smrg    SMI_MapMem(pScrn);
7797104f784Smrg    SMI_DisableVideo(pScrn);
78009885543Smrg
78109885543Smrg    /* detect the panel size */
78209885543Smrg    SMI_DetectPanelSize(pScrn);
78309885543Smrg
7847104f784Smrg    if(!IS_MSOC(pSmi)){
7857104f784Smrg	if (xf86LoadSubModule(pScrn, "i2c")) {
7867104f784Smrg	    SMI_I2CInit(pScrn);
7877104f784Smrg	}
7882ec8c4b4Smrg	xf86LoadSubModule(pScrn, "ddc");
78909885543Smrg    }
79009885543Smrg
79109885543Smrg    /*
79209885543Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
79309885543Smrg     */
79409885543Smrg    {
79509885543Smrg	Gamma zeros = { 0.0, 0.0, 0.0 };
79609885543Smrg
79709885543Smrg	if (!xf86SetGamma(pScrn, zeros)) {
79809885543Smrg	    SMI_EnableVideo(pScrn);
79909885543Smrg	    SMI_UnmapMem(pScrn);
8007104f784Smrg	    LEAVE(FALSE);
80109885543Smrg	}
80209885543Smrg    }
80309885543Smrg
8047104f784Smrg    SMI_DetectMCLK(pScrn);
80509885543Smrg
80609885543Smrg    /*
80709885543Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
80809885543Smrg     * and what sort of modes they can be used for.
80909885543Smrg     */
8107104f784Smrg    pSmi->clockRange.next = NULL;
8117104f784Smrg    pSmi->clockRange.minClock = 20000;
81209885543Smrg
8137104f784Smrg    if (SMI_LYNXM_SERIES(pSmi->Chipset) ||
8147104f784Smrg	IS_MSOC(pSmi))
8157104f784Smrg	pSmi->clockRange.maxClock = 200000;
81609885543Smrg    else
8177104f784Smrg        pSmi->clockRange.maxClock = 135000;
81809885543Smrg
8197104f784Smrg    pSmi->clockRange.clockIndex = -1;
8207104f784Smrg    pSmi->clockRange.interlaceAllowed = FALSE;
8217104f784Smrg    pSmi->clockRange.doubleScanAllowed = FALSE;
82209885543Smrg
8237104f784Smrg    if(!SMI_CrtcPreInit(pScrn))
8247104f784Smrg	LEAVE(FALSE);
8257104f784Smrg
8267104f784Smrg    if(!SMI_OutputPreInit(pScrn))
8277104f784Smrg	LEAVE(FALSE);
8287104f784Smrg
8297104f784Smrg    /* Only allow growing the screen dimensions if EXA is being used */
8307104f784Smrg    if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){
83109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
8322ec8c4b4Smrg
8332ec8c4b4Smrg	SMI_EnableVideo(pScrn);
8342ec8c4b4Smrg	SMI_UnmapMem(pScrn);
8357104f784Smrg	LEAVE(FALSE);
83609885543Smrg    }
83709885543Smrg
8382ec8c4b4Smrg    /* Ensure that the framebuffer size just set fits in video memory. */
8392ec8c4b4Smrg    {
8402ec8c4b4Smrg	int aligned_pitch = (pScrn->virtualX*pSmi->Bpp + 15) & ~15;
8412ec8c4b4Smrg
8422ec8c4b4Smrg	if(aligned_pitch * pScrn->virtualY > pSmi->FBReserved){
8432ec8c4b4Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video memory "
8442ec8c4b4Smrg		       "for the configured screen size (%dx%d) and color depth.\n",
8452ec8c4b4Smrg                       pScrn->virtualX, pScrn->virtualY);
8462ec8c4b4Smrg
8472ec8c4b4Smrg	    SMI_EnableVideo(pScrn);
8482ec8c4b4Smrg	    SMI_UnmapMem(pScrn);
8492ec8c4b4Smrg	    LEAVE(FALSE);
8502ec8c4b4Smrg	}
8512ec8c4b4Smrg    }
8522ec8c4b4Smrg
85309885543Smrg
8547104f784Smrg    SMI_EnableVideo(pScrn);
8557104f784Smrg    SMI_UnmapMem(pScrn);
8567104f784Smrg
8577104f784Smrg    if(pSmi->pVbe){
8587104f784Smrg       vbeFree(pSmi->pVbe);
8597104f784Smrg       pSmi->pVbe = NULL;
8607104f784Smrg    }
8617104f784Smrg    if(pSmi->pInt10){
8627104f784Smrg       xf86FreeInt10(pSmi->pInt10);
8637104f784Smrg       pSmi->pInt10 = NULL;
8647104f784Smrg    }
86509885543Smrg
86609885543Smrg    /* Set display resolution */
86709885543Smrg    xf86SetDpi(pScrn, 0, 0);
86809885543Smrg
8697104f784Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
87009885543Smrg	SMI_FreeRec(pScrn);
8717104f784Smrg	LEAVE(FALSE);
87209885543Smrg    }
87309885543Smrg
87409885543Smrg    /* Load XAA or EXA if needed */
87509885543Smrg    if (!pSmi->NoAccel) {
87609885543Smrg	if (!pSmi->useEXA) {
87709885543Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
87809885543Smrg		SMI_FreeRec(pScrn);
8797104f784Smrg		LEAVE(FALSE);
88009885543Smrg	    }
88109885543Smrg	} else {
88209885543Smrg	    XF86ModReqInfo req;
88309885543Smrg	    int errmaj, errmin;
88409885543Smrg
88509885543Smrg	    memset(&req, 0, sizeof(XF86ModReqInfo));
88609885543Smrg	    req.majorversion = 2;
8877104f784Smrg	    req.minorversion = 1;
88809885543Smrg
88909885543Smrg	    if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
89009885543Smrg				&req, &errmaj, &errmin)) {
89109885543Smrg		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
89209885543Smrg		SMI_FreeRec(pScrn);
8937104f784Smrg		LEAVE(FALSE);
89409885543Smrg	    }
89509885543Smrg	}
89609885543Smrg    }
89709885543Smrg
89809885543Smrg    /* Load ramdac if needed */
8997104f784Smrg    if (pSmi->HwCursor) {
90009885543Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
90109885543Smrg	    SMI_FreeRec(pScrn);
9027104f784Smrg	    LEAVE(FALSE);
90309885543Smrg	}
90409885543Smrg    }
90509885543Smrg
9067104f784Smrg    LEAVE(TRUE);
90709885543Smrg}
90809885543Smrg
90909885543Smrg/*
91009885543Smrg * This is called when VT switching back to the X server.  Its job is to
91109885543Smrg * reinitialise the video mode. We may wish to unmap video/MMIO memory too.
91209885543Smrg */
91309885543Smrg
91409885543Smrgstatic Bool
91509885543SmrgSMI_EnterVT(int scrnIndex, int flags)
91609885543Smrg{
91709885543Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
91809885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
91909885543Smrg
9207104f784Smrg    ENTER();
92109885543Smrg
92209885543Smrg    /* Enable MMIO and map memory */
92309885543Smrg    SMI_MapMem(pScrn);
92409885543Smrg
9257104f784Smrg    pSmi->Save(pScrn);
92609885543Smrg
9277104f784Smrg    /* FBBase may have changed after remapping the memory */
9287104f784Smrg    pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
9297104f784Smrg				       -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
9307104f784Smrg    pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
93109885543Smrg
9327104f784Smrg    if(pSmi->useEXA)
9337104f784Smrg       pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
93409885543Smrg
9357104f784Smrg    /* Do the CRTC independent initialization */
9367104f784Smrg    if(!SMI_HWInit(pScrn))
9377104f784Smrg	LEAVE(FALSE);
93809885543Smrg
9397104f784Smrg    /* Initialize the chosen modes */
9407104f784Smrg    if (!xf86SetDesiredModes(pScrn))
9417104f784Smrg	LEAVE(FALSE);
94209885543Smrg
9437104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
9447104f784Smrg		   "Done writing mode.  Register dump:\n");
9457104f784Smrg    SMI_PrintRegs(pScrn);
94609885543Smrg
94709885543Smrg    /* Reset the grapics engine */
94809885543Smrg    if (!pSmi->NoAccel)
94909885543Smrg	SMI_EngineReset(pScrn);
95009885543Smrg
9517104f784Smrg    LEAVE(TRUE);
95209885543Smrg}
95309885543Smrg
95409885543Smrg/*
95509885543Smrg * This is called when VT switching away from the X server.  Its job is to
95609885543Smrg * restore the previous (text) mode. We may wish to remap video/MMIO memory
95709885543Smrg * too.
95809885543Smrg */
95909885543Smrg
96009885543Smrgstatic void
96109885543SmrgSMI_LeaveVT(int scrnIndex, int flags)
96209885543Smrg{
9637104f784Smrg    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
9647104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
96509885543Smrg
9667104f784Smrg    ENTER();
96709885543Smrg
9687104f784Smrg    SMI_AccelSync(pScrn);
96909885543Smrg
9707104f784Smrg    /* Ensure that the rotation BlockHandler is unwrapped, and the shadow
9717104f784Smrg       pixmaps are deallocated, as the video memory is going to be
9727104f784Smrg       unmapped.  */
9737104f784Smrg    xf86RotateCloseScreen(pScrn->pScreen);
97409885543Smrg
9757104f784Smrg    /* Pixmaps that by chance get allocated near the former aperture
9767104f784Smrg       address shouldn't be considered offscreen. */
9777104f784Smrg    if(pSmi->useEXA)
9787104f784Smrg       pSmi->EXADriverPtr->memoryBase=NULL;
97909885543Smrg
9807104f784Smrg    /* Clear frame buffer */
9817104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
9827104f784Smrg
9837104f784Smrg    if (!IS_MSOC(pSmi)) {
9847104f784Smrg	vgaHWPtr	hwp = VGAHWPTR(pScrn);
9857104f784Smrg
9867104f784Smrg	SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
98709885543Smrg    }
9887104f784Smrg    else
9897104f784Smrg	SMI501_WriteMode(pScrn, pSmi->save);
99009885543Smrg
99109885543Smrg    SMI_UnmapMem(pScrn);
99209885543Smrg
9937104f784Smrg    LEAVE();
99409885543Smrg}
99509885543Smrg
99609885543Smrgstatic void
9977104f784SmrgSMI_DetectPanelSize(ScrnInfoPtr pScrn)
99809885543Smrg{
9997104f784Smrg    char	*s;
10007104f784Smrg    int		 width, height;
10017104f784Smrg    SMIPtr	 pSmi = SMIPTR(pScrn);
100209885543Smrg
10037104f784Smrg    pSmi->lcdWidth  = 0;
10047104f784Smrg    pSmi->lcdHeight = 0;
10057104f784Smrg    if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) {
10067104f784Smrg	if (sscanf(s, "%dx%d", &width, &height) != 2)
10077104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
10087104f784Smrg		       "Invalid PanelSize option: %s\n", s);
10097104f784Smrg	else {
10107104f784Smrg	    pSmi->lcdWidth  = width;
10117104f784Smrg	    pSmi->lcdHeight = height;
101209885543Smrg	}
101309885543Smrg    }
101409885543Smrg
10157104f784Smrg    if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) {
10167104f784Smrg	/* panel size detection ... requires BIOS call on 730 hardware */
10177104f784Smrg	if (pSmi->Chipset == SMI_COUGAR3DR) {
10187104f784Smrg	    if (pSmi->pInt10 != NULL) {
10197104f784Smrg		pSmi->pInt10->num = 0x10;
10207104f784Smrg		pSmi->pInt10->ax  = 0x5F00;
10217104f784Smrg		pSmi->pInt10->bx  = 0;
10227104f784Smrg		pSmi->pInt10->cx  = 0;
10237104f784Smrg		pSmi->pInt10->dx  = 0;
10247104f784Smrg		xf86ExecX86int10(pSmi->pInt10);
10257104f784Smrg		if (pSmi->pInt10->ax == 0x005F) {
10267104f784Smrg		    switch (pSmi->pInt10->cx & 0x0F) {
10277104f784Smrg			case PANEL_640x480:
10287104f784Smrg			    pSmi->lcdWidth  = 640;
10297104f784Smrg			    pSmi->lcdHeight = 480;
10307104f784Smrg			    break;
10317104f784Smrg			case PANEL_800x600:
10327104f784Smrg			    pSmi->lcdWidth  = 800;
10337104f784Smrg			    pSmi->lcdHeight = 600;
10347104f784Smrg			    break;
10357104f784Smrg			case PANEL_1024x768:
10367104f784Smrg			    pSmi->lcdWidth  = 1024;
10377104f784Smrg			    pSmi->lcdHeight = 768;
10387104f784Smrg			    break;
10397104f784Smrg			case PANEL_1280x1024:
10407104f784Smrg			    pSmi->lcdWidth  = 1280;
10417104f784Smrg			    pSmi->lcdHeight = 1024;
10427104f784Smrg			    break;
10437104f784Smrg			case PANEL_1600x1200:
10447104f784Smrg			    pSmi->lcdWidth  = 1600;
10457104f784Smrg			    pSmi->lcdHeight = 1200;
10467104f784Smrg			    break;
10477104f784Smrg			case PANEL_1400x1050:
10487104f784Smrg			    pSmi->lcdWidth  = 1400;
10497104f784Smrg			    pSmi->lcdHeight = 1050;
10507104f784Smrg			    break;
10517104f784Smrg		    }
105209885543Smrg
10537104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10547104f784Smrg			       "Detected panel size via BIOS: %d x %d\n",
10557104f784Smrg			       pSmi->lcdWidth, pSmi->lcdHeight);
105609885543Smrg		}
10577104f784Smrg		else
10587104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10597104f784Smrg			       "BIOS error during 730 panel detection!\n");
106009885543Smrg	    }
10617104f784Smrg	    else  {
10627104f784Smrg		/* int10 support isn't setup on the second call to this function,
10637104f784Smrg		  o if this is the second call, don't do detection again */
10647104f784Smrg		if (pSmi->lcd == 0)
10657104f784Smrg		    /* If we get here, int10 support is not loaded or not working */
10667104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10677104f784Smrg			       "No BIOS support for 730 panel detection!\n");
106809885543Smrg	    }
106909885543Smrg
10707104f784Smrg	    /* Set this to indicate that we've done the detection */
10717104f784Smrg	    pSmi->lcd = 1;
107209885543Smrg	}
10737104f784Smrg	else if (IS_MSOC(pSmi)) {
10747104f784Smrg	    pSmi->lcdWidth  = (READ_SCR(pSmi, PANEL_WWIDTH)  >> 16) & 2047;
10757104f784Smrg	    pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047;
107609885543Smrg	}
10777104f784Smrg	else {
10787104f784Smrg	    /* panel size detection for hardware other than 730 */
10797104f784Smrg	    pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10807104f784Smrg				     0x31) & 0x01;
108109885543Smrg
10827104f784Smrg	    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10837104f784Smrg			     0x30) & 0x01) {
10847104f784Smrg		pSmi->lcd <<= 1;
10857104f784Smrg	    }
10867104f784Smrg	    switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10877104f784Smrg				 0x30) & 0x0C) {
10887104f784Smrg		case 0x00:
108909885543Smrg		    pSmi->lcdWidth  = 640;
109009885543Smrg		    pSmi->lcdHeight = 480;
109109885543Smrg		    break;
10927104f784Smrg		case 0x04:
109309885543Smrg		    pSmi->lcdWidth  = 800;
109409885543Smrg		    pSmi->lcdHeight = 600;
109509885543Smrg		    break;
10967104f784Smrg		case 0x08:
10977104f784Smrg		    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10987104f784Smrg				     0x74) & 0x02) {
10997104f784Smrg			pSmi->lcdWidth  = 1024;
11007104f784Smrg			pSmi->lcdHeight = 600;
11017104f784Smrg		    }
11027104f784Smrg		    else {
11037104f784Smrg			pSmi->lcdWidth  = 1024;
11047104f784Smrg			pSmi->lcdHeight = 768;
11057104f784Smrg		    }
110609885543Smrg		    break;
11077104f784Smrg		case 0x0C:
110809885543Smrg		    pSmi->lcdWidth  = 1280;
110909885543Smrg		    pSmi->lcdHeight = 1024;
111009885543Smrg		    break;
111109885543Smrg	    }
111209885543Smrg	}
111309885543Smrg    }
111409885543Smrg
11157104f784Smrg    if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0)
11167104f784Smrg	pSmi->lcdWidth = 1024;
11177104f784Smrg    if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0)
11187104f784Smrg	pSmi->lcdHeight = 768;
11197104f784Smrg
112009885543Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
112109885543Smrg	       (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
112209885543Smrg	       pSmi->lcdWidth, pSmi->lcdHeight);
112309885543Smrg
112409885543Smrg}
112509885543Smrg
11267104f784Smrgstatic void
11277104f784SmrgSMI_DetectMCLK(ScrnInfoPtr pScrn)
11287104f784Smrg{
11297104f784Smrg    double		real;
11307104f784Smrg    MSOCClockRec	clock;
11317104f784Smrg    int			mclk, mxclk;
11327104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
11337104f784Smrg
11347104f784Smrg    /* MCLK defaults */
11357104f784Smrg    if (pSmi->Chipset == SMI_LYNXEMplus){
11367104f784Smrg	/* The SM712 can be safely clocked up to 157MHz, according to
11377104f784Smrg	   Silicon Motion engineers. */
11387104f784Smrg	pSmi->MCLK = 157000;
11397104f784Smrg
11402ec8c4b4Smrg    } else if (IS_MSOC(pSmi)) {
11412ec8c4b4Smrg       /* Set some sane defaults for the clock settings if we are on a
11422ec8c4b4Smrg          SM502 and it's likely to be uninitialized. */
11432ec8c4b4Smrg
11442ec8c4b4Smrg       if (!xf86IsPrimaryPci(pSmi->PciInfo) &&
11452ec8c4b4Smrg           (READ_SCR(pSmi, DEVICE_ID) & 0xFF) >= 0xC0) {
11462ec8c4b4Smrg          pSmi->MCLK = 112000;
11472ec8c4b4Smrg          pSmi->MXCLK = 144000;
11482ec8c4b4Smrg       }
11492ec8c4b4Smrg
11502ec8c4b4Smrg    } else {
11512ec8c4b4Smrg        pSmi->MCLK = 0;
11522ec8c4b4Smrg        pSmi->MXCLK = 0;
11532ec8c4b4Smrg    }
11547104f784Smrg
11557104f784Smrg    /* MCLK from user settings */
11567104f784Smrg    if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
11577104f784Smrg	if (IS_MSOC(pSmi) || (int)real <= 120) {
11587104f784Smrg	    pSmi->MCLK = (int)(real * 1000.0);
11597104f784Smrg	} else {
11607104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
11617104f784Smrg		       "Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
11627104f784Smrg		       real);
11637104f784Smrg	}
11647104f784Smrg    }
11657104f784Smrg    mclk = pSmi->MCLK;
11667104f784Smrg
11677104f784Smrg    if (IS_MSOC(pSmi)) {
11687104f784Smrg	clock.value = READ_SCR(pSmi, CURRENT_CLOCK);
11697104f784Smrg	if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK,
11707104f784Smrg			      OPTUNITS_MHZ, &real))
11717104f784Smrg	    pSmi->MXCLK = (int)(real * 1000.0);
11727104f784Smrg    }
11737104f784Smrg
11747104f784Smrg    /* Already programmed MCLK */
11757104f784Smrg    if (pSmi->MCLK == 0) {
11767104f784Smrg	if (IS_MSOC(pSmi))
11777104f784Smrg	    mclk = ((clock.f.m_select ? 336 : 288) /
11787104f784Smrg		    ((clock.f.m_divider ? 3 : 1) <<
11797104f784Smrg		     (unsigned)clock.f.m_shift)) * 1000;
11807104f784Smrg	else {
11817104f784Smrg	    unsigned char	shift, m, n;
11827104f784Smrg
11837104f784Smrg	    m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
11847104f784Smrg	    n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
11857104f784Smrg	    switch (n >> 6) {
11867104f784Smrg		case 1:
11877104f784Smrg		    shift = 4;
11887104f784Smrg		    break;
11897104f784Smrg		case 2:
11907104f784Smrg		    shift = 2;
11917104f784Smrg		    break;
11927104f784Smrg		default:
11937104f784Smrg		    shift = 1;
11947104f784Smrg		    break;
11957104f784Smrg	    }
11967104f784Smrg	    n &= 0x3F;
11977104f784Smrg	    mclk = ((1431818 * m) / n / shift + 50) / 100;
11987104f784Smrg	}
11997104f784Smrg    }
12007104f784Smrg
12017104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0);
12027104f784Smrg    if (IS_MSOC(pSmi)) {
12037104f784Smrg	if (pSmi->MXCLK == 0) {
12047104f784Smrg	    mxclk = ((clock.f.m1_select ? 336 : 288) /
12057104f784Smrg		     ((clock.f.m1_divider ? 3 : 1) <<
12067104f784Smrg		      (unsigned)clock.f.m1_shift)) * 1000;
12077104f784Smrg	}
12087104f784Smrg	else
12097104f784Smrg	    mxclk = pSmi->MXCLK;
12107104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0);
12117104f784Smrg    }
12127104f784Smrg}
12137104f784Smrg
121409885543Smrgstatic Bool
12157104f784SmrgSMI_MapMmio(ScrnInfoPtr pScrn)
121609885543Smrg{
12177104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
12187104f784Smrg    CARD32	memBase;
121909885543Smrg
12207104f784Smrg    SMI_EnableMmio(pScrn);
122109885543Smrg
122209885543Smrg    switch (pSmi->Chipset) {
12237104f784Smrg	case SMI_COUGAR3DR:
12247104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
12257104f784Smrg	    pSmi->MapSize = 0x200000;
12267104f784Smrg	    break;
12277104f784Smrg	case SMI_LYNX3D:
12287104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000;
12297104f784Smrg	    pSmi->MapSize = 0x180000;
12307104f784Smrg	    break;
12317104f784Smrg	case SMI_LYNXEM:
12327104f784Smrg	case SMI_LYNXEMplus:
12337104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
12347104f784Smrg	    pSmi->MapSize = 0x400000;
12357104f784Smrg	    break;
12367104f784Smrg	case SMI_LYNX3DM:
12377104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
12387104f784Smrg	    pSmi->MapSize = 0x200000;
12397104f784Smrg	    break;
12407104f784Smrg	case SMI_MSOC:
12417104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
12427104f784Smrg	    pSmi->MapSize = 0x200000;
12437104f784Smrg	    break;
12447104f784Smrg	default:
12457104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
12467104f784Smrg	    pSmi->MapSize = 0x10000;
12477104f784Smrg	    break;
124809885543Smrg    }
12497104f784Smrg
12507104f784Smrg#ifndef XSERVER_LIBPCIACCESS
125109885543Smrg    pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
125209885543Smrg				  memBase, pSmi->MapSize);
12537104f784Smrg#else
12547104f784Smrg    {
12557104f784Smrg	void	**result = (void**)&pSmi->MapBase;
12567104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
12577104f784Smrg					     memBase,
12587104f784Smrg					     pSmi->MapSize,
12597104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE,
12607104f784Smrg					     result);
12617104f784Smrg
12627104f784Smrg	if (err)
12637104f784Smrg	    return (FALSE);
12647104f784Smrg    }
12657104f784Smrg#endif
126609885543Smrg
126709885543Smrg    if (pSmi->MapBase == NULL) {
126809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
126909885543Smrg		   "MMIO registers.\n");
12707104f784Smrg	return (FALSE);
127109885543Smrg    }
127209885543Smrg
127309885543Smrg    switch (pSmi->Chipset) {
12747104f784Smrg	case SMI_COUGAR3DR:
12757104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
12767104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
12777104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
12787104f784Smrg	    pSmi->FPRBase = pSmi->MapBase + 0x005800;
12797104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
12807104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
12817104f784Smrg	    pSmi->DataPortSize = 0x100000;
12827104f784Smrg	    break;
12837104f784Smrg	case SMI_LYNX3D:
12847104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
12857104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
12867104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
12877104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x040000;
12887104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x080000;
12897104f784Smrg	    pSmi->DataPortSize = 0x100000;
12907104f784Smrg	    break;
12917104f784Smrg	case SMI_LYNXEM:
12927104f784Smrg	case SMI_LYNXEMplus:
12937104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x008000;
12947104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x00C000;
12957104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x00E000;
12967104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x300000;
12977104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
12987104f784Smrg	    pSmi->DataPortSize = 0x8000 /*0x200000*/;
12997104f784Smrg	    break;
13007104f784Smrg	case SMI_LYNX3DM:
13017104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
13027104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
13037104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
13047104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
13057104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
13067104f784Smrg	    pSmi->DataPortSize = 0x100000;
13077104f784Smrg	    break;
13087104f784Smrg	case SMI_MSOC:
13097104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x100000;
13107104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000000;
13117104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x090000;
13127104f784Smrg	    pSmi->DCRBase = pSmi->MapBase + 0x080000;
13137104f784Smrg	    pSmi->SCRBase = pSmi->MapBase + 0x000000;
13147104f784Smrg	    pSmi->IOBase = 0;
13157104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x110000;
13167104f784Smrg	    pSmi->DataPortSize = 0x10000;
13177104f784Smrg	    break;
13187104f784Smrg	default:
13197104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x8000;
13207104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0xC000;
13217104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0xE000;
13227104f784Smrg	    pSmi->IOBase  = NULL;
13237104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase;
13247104f784Smrg	    pSmi->DataPortSize = 0x8000;
13257104f784Smrg	    break;
132609885543Smrg    }
13277104f784Smrg
132809885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
132909885543Smrg		   "Physical MMIO at 0x%08lX\n", (unsigned long)memBase);
133009885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133109885543Smrg		   "Logical MMIO at %p - %p\n", pSmi->MapBase,
133209885543Smrg		   pSmi->MapBase + pSmi->MapSize - 1);
133309885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133409885543Smrg		   "DPR=%p, VPR=%p, IOBase=%p\n",
133509885543Smrg		   pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase);
133609885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133709885543Smrg		   "DataPort=%p - %p\n", pSmi->DataPortBase,
133809885543Smrg		   pSmi->DataPortBase + pSmi->DataPortSize - 1);
133909885543Smrg
13407104f784Smrg    return (TRUE);
13417104f784Smrg}
134209885543Smrg
13432ec8c4b4Smrg/* HACK - In some cases the BIOS hasn't filled in the "scratchpad
13442ec8c4b4Smrg   registers" (SR71) with the right amount of memory installed (e.g. MIPS
13452ec8c4b4Smrg   platform). Probe it manually. */
13462ec8c4b4Smrgstatic unsigned long
13472ec8c4b4SmrgSMI_ProbeMem(ScrnInfoPtr pScrn, unsigned long mem_skip, unsigned long mem_max)
13482ec8c4b4Smrg{
13492ec8c4b4Smrg    SMIPtr pSmi = SMIPTR(pScrn);
13502ec8c4b4Smrg    unsigned long mem_probe = 1024*1024;
13512ec8c4b4Smrg    unsigned long aperture_base;
13522ec8c4b4Smrg    void* mem;
13532ec8c4b4Smrg
13542ec8c4b4Smrg    ENTER();
13552ec8c4b4Smrg
13562ec8c4b4Smrg    aperture_base = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + mem_skip;
13572ec8c4b4Smrg    mem_max = min(mem_max , PCI_REGION_SIZE(pSmi->PciInfo, 0) - mem_skip);
13582ec8c4b4Smrg
13592ec8c4b4Smrg#ifndef XSERVER_LIBPCIACCESS
13602ec8c4b4Smrg    mem = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
13612ec8c4b4Smrg			aperture_base, mem_max);
13622ec8c4b4Smrg
13632ec8c4b4Smrg    if(!mem)
13642ec8c4b4Smrg	LEAVE(0);
13652ec8c4b4Smrg#else
13662ec8c4b4Smrg    if(pci_device_map_range(pSmi->PciInfo, aperture_base, mem_max,
13672ec8c4b4Smrg			    PCI_DEV_MAP_FLAG_WRITABLE, &mem))
13682ec8c4b4Smrg	LEAVE(0);
13692ec8c4b4Smrg#endif
13702ec8c4b4Smrg
13712ec8c4b4Smrg    while(mem_probe <= mem_max){
13722ec8c4b4Smrg	MMIO_OUT32(mem, mem_probe-4, 0x55555555);
13732ec8c4b4Smrg	if(MMIO_IN32(mem, mem_probe-4) != 0x55555555)
13742ec8c4b4Smrg	    break;
13752ec8c4b4Smrg
13762ec8c4b4Smrg	MMIO_OUT32(mem, mem_probe-4, 0xAAAAAAAA);
13772ec8c4b4Smrg	if(MMIO_IN32(mem, mem_probe-4) != 0xAAAAAAAA)
13782ec8c4b4Smrg	    break;
13792ec8c4b4Smrg
13802ec8c4b4Smrg	mem_probe <<= 1;
13812ec8c4b4Smrg    }
13822ec8c4b4Smrg
13832ec8c4b4Smrg#ifndef XSERVER_LIBPCIACCESS
13842ec8c4b4Smrg    xf86UnMapVidMem(pScrn->scrnIndex, mem, mem_max);
13852ec8c4b4Smrg#else
13862ec8c4b4Smrg    pci_device_unmap_range(pSmi->PciInfo, mem, mem_max);
13872ec8c4b4Smrg#endif
13882ec8c4b4Smrg
13892ec8c4b4Smrg    LEAVE(mem_probe >> 1);
13902ec8c4b4Smrg}
13912ec8c4b4Smrg
13927104f784Smrgstatic Bool
13937104f784SmrgSMI_DetectMem(ScrnInfoPtr pScrn)
13947104f784Smrg{
13957104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
13967104f784Smrg    MessageType from;
139709885543Smrg
13987104f784Smrg    if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){
13997104f784Smrg	pSmi->videoRAMKBytes = pScrn->videoRam;
14007104f784Smrg	from = X_CONFIG;
14017104f784Smrg    }
14027104f784Smrg    else {
14037104f784Smrg	unsigned char	 config;
14047104f784Smrg	static int	 lynx3d_table[4]  = {  0, 2, 4, 6 };
14057104f784Smrg	static int	 lynx3dm_table[4] = { 16, 2, 4, 8 };
14067104f784Smrg	static int	 msoc_table[8]    = {  4, 8, 16, 32, 64, 2, 0, 0 };
14077104f784Smrg	static int	 default_table[4] = {  1, 2, 4, 0 };
14087104f784Smrg
14097104f784Smrg	if (IS_MSOC(pSmi)) {
14107104f784Smrg	    config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7;
14117104f784Smrg	    pSmi->videoRAMKBytes = msoc_table[config] * 1024 -
14127104f784Smrg		SHARED_USB_DMA_BUFFER_SIZE;
14137104f784Smrg	}
14147104f784Smrg	else {
14157104f784Smrg	    config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
14167104f784Smrg	    switch (pSmi->Chipset) {
14177104f784Smrg		case SMI_LYNX3D:
14187104f784Smrg		    pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 +
14197104f784Smrg			512;
14207104f784Smrg		    break;
14212ec8c4b4Smrg		case SMI_LYNXEMplus:
14222ec8c4b4Smrg		    pSmi->videoRAMKBytes = SMI_ProbeMem(pScrn, 0, 0x400000) / 1024;
14232ec8c4b4Smrg		    break;
14247104f784Smrg		case SMI_LYNX3DM:
14257104f784Smrg		    pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024;
14267104f784Smrg		    break;
14277104f784Smrg		case SMI_COUGAR3DR:
14287104f784Smrg		    /* DANGER - Cougar3DR BIOS is broken - hardcode video ram
14297104f784Smrg		     * size per instructions from Silicon Motion engineers */
14307104f784Smrg		    pSmi->videoRAMKBytes = 16 * 1024;
14317104f784Smrg		    break;
14327104f784Smrg		default:
14337104f784Smrg		    pSmi->videoRAMKBytes = default_table[config >> 6] * 1024;
14347104f784Smrg		    break;
14357104f784Smrg	    }
143609885543Smrg	}
14377104f784Smrg	from = X_PROBED;
14387104f784Smrg    }
143909885543Smrg
14407104f784Smrg    pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
14417104f784Smrg    pScrn->videoRam     = pSmi->videoRAMKBytes;
14427104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
14437104f784Smrg	       "videoram: %dkB\n", pSmi->videoRAMKBytes);
144409885543Smrg
14457104f784Smrg    return (TRUE);
14467104f784Smrg}
144709885543Smrg
14487104f784SmrgBool
14497104f784SmrgSMI_MapMem(ScrnInfoPtr pScrn)
14507104f784Smrg{
14517104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
14527104f784Smrg    vgaHWPtr hwp;
145309885543Smrg
14547104f784Smrg    ENTER();
14557104f784Smrg
14567104f784Smrg    if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE)
14577104f784Smrg	LEAVE(FALSE);
14587104f784Smrg
14597104f784Smrg    pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
14607104f784Smrg
14617104f784Smrg    if (pSmi->Chipset == SMI_LYNX3DM)
14627104f784Smrg	pSmi->fbMapOffset = 0x200000;
14637104f784Smrg    else
14647104f784Smrg	pSmi->fbMapOffset = 0x0;
14657104f784Smrg
14667104f784Smrg#ifndef XSERVER_LIBPCIACCESS
14677104f784Smrg    pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex,
14687104f784Smrg				 VIDMEM_FRAMEBUFFER,
14697104f784Smrg				 pSmi->PciTag,
14707104f784Smrg				 pScrn->memPhysBase + pSmi->fbMapOffset,
14717104f784Smrg				 pSmi->videoRAMBytes);
14727104f784Smrg#else
14737104f784Smrg    {
14747104f784Smrg	void	**result = (void**)&pSmi->FBBase;
14757104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
14767104f784Smrg					     pScrn->memPhysBase +
14777104f784Smrg					     pSmi->fbMapOffset,
14787104f784Smrg					     pSmi->videoRAMBytes,
14797104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE |
14807104f784Smrg					     PCI_DEV_MAP_FLAG_WRITE_COMBINE,
14817104f784Smrg					     result);
14827104f784Smrg
14837104f784Smrg	if (err)
14847104f784Smrg	    LEAVE(FALSE);
14857104f784Smrg    }
14867104f784Smrg#endif
14877104f784Smrg
14887104f784Smrg    if (pSmi->FBBase == NULL) {
14897104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
14907104f784Smrg		   "Internal error: could not map framebuffer.\n");
14917104f784Smrg	LEAVE(FALSE);
14927104f784Smrg    }
14937104f784Smrg
14947104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
14957104f784Smrg		   "Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
14967104f784Smrg		   pScrn->memPhysBase, pSmi->fbMapOffset);
14977104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
14987104f784Smrg		   "Logical frame buffer at %p - %p\n", pSmi->FBBase,
14997104f784Smrg		   pSmi->FBBase + pSmi->videoRAMBytes - 1);
15007104f784Smrg
15017104f784Smrg    if (IS_MSOC(pSmi)) {
15027104f784Smrg	/* Reserve space for panel cursr, and crt if in dual head mode */
15037104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
15047104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15057104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE);
15067104f784Smrg#else
15077104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15087104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE);
15097104f784Smrg
15107104f784Smrg# if SMI501_CLI_DEBUG
15117104f784Smrg	if (pSmi->useEXA) {
15127104f784Smrg	    pSmi->batch_active = FALSE;
15137104f784Smrg	    pSmi->batch_length = 4096;
15147104f784Smrg	    pSmi->FBReserved -= pSmi->batch_length << 3;
15157104f784Smrg	    pSmi->batch_offset = pSmi->FBReserved;
15167104f784Smrg	    pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset);
15177104f784Smrg	    pSmi->batch_finish = -1;
15187104f784Smrg	    pSmi->batch_index = 0;
15197104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
15207104f784Smrg		       "Using command list interpreter debug code\n");
15217104f784Smrg	}
15227104f784Smrg# endif
15237104f784Smrg
15247104f784Smrg#endif
15257104f784Smrg    }
15267104f784Smrg    else {
15277104f784Smrg	/* Set up offset to hwcursor memory area, at the end of
15287104f784Smrg	 * the frame buffer.
15297104f784Smrg	 */
15307104f784Smrg	pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE;
153109885543Smrg	/* set up the fifo reserved space */
153209885543Smrg	if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ {
153309885543Smrg	    CARD32 fifoOffset = 0;
15347104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15357104f784Smrg				       0x46) << 3;
15367104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15377104f784Smrg				       0x47) << 11;
15387104f784Smrg	    fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15397104f784Smrg					0x49) & 0x1C) << 17;
154009885543Smrg	    pSmi->FBReserved = fifoOffset;	/* PDR#1074 */
154109885543Smrg	}
15427104f784Smrg	else
15437104f784Smrg	    pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
154409885543Smrg
15457104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n",
15467104f784Smrg		   (unsigned long)pSmi->FBCursorOffset);
154709885543Smrg
15487104f784Smrg	/* Assign hwp->MemBase & IOBase here */
15497104f784Smrg	hwp = VGAHWPTR(pScrn);
15507104f784Smrg	if (pSmi->IOBase != NULL)
15517104f784Smrg	    vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
15527104f784Smrg	vgaHWGetIOBase(hwp);
155309885543Smrg
15547104f784Smrg	/* Map the VGA memory when the primary video */
15557104f784Smrg	if (xf86IsPrimaryPci(pSmi->PciInfo)) {
15567104f784Smrg	    hwp->MapSize = 0x10000;
15577104f784Smrg	    if (!vgaHWMapMem(pScrn))
15587104f784Smrg		LEAVE(FALSE);
15597104f784Smrg	    pSmi->PrimaryVidMapped = TRUE;
156009885543Smrg	}
156109885543Smrg    }
156209885543Smrg
15637104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n",
15647104f784Smrg	       (unsigned long)pSmi->FBReserved);
15657104f784Smrg
15667104f784Smrg    LEAVE(TRUE);
156709885543Smrg}
156809885543Smrg
156909885543Smrg/* UnMapMem - contains half of pre-4.0 EnterLeave function.  The EnterLeave
157009885543Smrg * function which en/disable access to IO ports and ext. regs
157109885543Smrg */
157209885543Smrg
15737104f784Smrgvoid
157409885543SmrgSMI_UnmapMem(ScrnInfoPtr pScrn)
157509885543Smrg{
157609885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
157709885543Smrg
15787104f784Smrg    ENTER();
157909885543Smrg
158009885543Smrg    /* Unmap VGA mem if mapped. */
158109885543Smrg    if (pSmi->PrimaryVidMapped) {
158209885543Smrg	vgaHWUnmapMem(pScrn);
158309885543Smrg	pSmi->PrimaryVidMapped = FALSE;
158409885543Smrg    }
158509885543Smrg
158609885543Smrg    SMI_DisableMmio(pScrn);
158709885543Smrg
15887104f784Smrg    if (pSmi->MapBase) {
15897104f784Smrg#ifndef XSERVER_LIBPCIACCESS
15907104f784Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase,
15917104f784Smrg			pSmi->MapSize);
15927104f784Smrg#else
15937104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase,
15947104f784Smrg			       pSmi->MapSize);
15957104f784Smrg#endif
15967104f784Smrg	pSmi->MapBase = NULL;
15977104f784Smrg    }
15987104f784Smrg
15997104f784Smrg    if (pSmi->FBBase) {
16007104f784Smrg#ifndef XSERVER_LIBPCIACCESS
160109885543Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
160209885543Smrg			pSmi->videoRAMBytes);
16037104f784Smrg#else
16047104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase,
16057104f784Smrg			       pSmi->videoRAMBytes);
16067104f784Smrg#endif
16077104f784Smrg	pSmi->FBBase = NULL;
160809885543Smrg    }
160909885543Smrg
16107104f784Smrg    LEAVE();
161109885543Smrg}
161209885543Smrg
161309885543Smrg/* This gets called at the start of each server generation. */
161409885543Smrg
161509885543Smrgstatic Bool
161609885543SmrgSMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
161709885543Smrg{
16187104f784Smrg    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
16197104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
16207104f784Smrg    EntityInfoPtr	pEnt;
162109885543Smrg
16227104f784Smrg    ENTER();
162309885543Smrg
162409885543Smrg    /* Map MMIO regs and framebuffer */
16257104f784Smrg    if (!SMI_MapMem(pScrn))
16267104f784Smrg	LEAVE(FALSE);
162709885543Smrg
162809885543Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
162909885543Smrg
16307104f784Smrg    if (!pSmi->pInt10 && pSmi->useBIOS) {
16317104f784Smrg	pSmi->pInt10 = xf86InitInt10(pEnt->index);
163209885543Smrg    }
16337104f784Smrg    if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
16347104f784Smrg	pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
163509885543Smrg    }
163609885543Smrg
16377104f784Smrg    /* Save the chip/graphics state */
16387104f784Smrg    pSmi->Save(pScrn);
163909885543Smrg
16407104f784Smrg    /* Fill in some needed pScrn fields */
16417104f784Smrg    pScrn->vtSema = TRUE;
16427104f784Smrg    pScrn->pScreen = pScreen;
164309885543Smrg
16447104f784Smrg    pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
164509885543Smrg
16467104f784Smrg    pSmi->fbArea = NULL;
16477104f784Smrg    pSmi->FBOffset = 0;
16487104f784Smrg    pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
164909885543Smrg
16507104f784Smrg    /* Clear frame buffer */
16517104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
165209885543Smrg
165309885543Smrg    /*
16547104f784Smrg     * The next step is to setup the screen's visuals, and initialise the
16557104f784Smrg     * framebuffer code.  In cases where the framebuffer's default choises for
16567104f784Smrg     * things like visual layouts and bits per RGB are OK, this may be as simple
16577104f784Smrg     * as calling the framebuffer's ScreenInit() function.  If not, the visuals
16587104f784Smrg     * will need to be setup before calling a fb ScreenInit() function and fixed
16597104f784Smrg     * up after.
16607104f784Smrg     */
166109885543Smrg
16627104f784Smrg    /*
16637104f784Smrg     * Reset the visual list.
16647104f784Smrg     */
16657104f784Smrg    miClearVisualTypes();
166609885543Smrg
16677104f784Smrg    /* Setup the visuals we support. */
166809885543Smrg
16697104f784Smrg    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
16707104f784Smrg			  pScrn->rgbBits, pScrn->defaultVisual))
16717104f784Smrg	LEAVE(FALSE);
167209885543Smrg
16737104f784Smrg    if (!miSetPixmapDepths ())
16747104f784Smrg	LEAVE(FALSE);
167509885543Smrg
16767104f784Smrg    /*
16777104f784Smrg     * Call the framebuffer layer's ScreenInit function
16787104f784Smrg     */
167909885543Smrg
16807104f784Smrg    DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
16817104f784Smrg	  pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
16827104f784Smrg    if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
16837104f784Smrg		     pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
16847104f784Smrg	LEAVE(FALSE);
168509885543Smrg
16867104f784Smrg    xf86SetBlackWhitePixels(pScreen);
168709885543Smrg
16887104f784Smrg    if (pScrn->bitsPerPixel > 8) {
16897104f784Smrg	VisualPtr visual;
16907104f784Smrg	/* Fixup RGB ordering */
16917104f784Smrg	visual = pScreen->visuals + pScreen->numVisuals;
16927104f784Smrg	while (--visual >= pScreen->visuals) {
16937104f784Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
16947104f784Smrg		visual->offsetRed   = pScrn->offset.red;
16957104f784Smrg		visual->offsetGreen = pScrn->offset.green;
16967104f784Smrg		visual->offsetBlue  = pScrn->offset.blue;
16977104f784Smrg		visual->redMask     = pScrn->mask.red;
16987104f784Smrg		visual->greenMask   = pScrn->mask.green;
16997104f784Smrg		visual->blueMask    = pScrn->mask.blue;
17007104f784Smrg	    }
170109885543Smrg	}
170209885543Smrg    }
170309885543Smrg
17047104f784Smrg    /* must be after RGB ordering fixed */
17057104f784Smrg    fbPictureInit(pScreen, 0, 0);
17067104f784Smrg
17077104f784Smrg    /* Do the CRTC independent initialization */
17087104f784Smrg    if(!SMI_HWInit(pScrn))
17097104f784Smrg	LEAVE(FALSE);
171009885543Smrg
17117104f784Smrg    /* Unless using EXA, regardless or using XAA or not, needs offscreen
17127104f784Smrg     * management at least for video. */
17137104f784Smrg    if (pSmi->NoAccel || !pSmi->useEXA) {
17147104f784Smrg	int		numLines;
17157104f784Smrg	BoxRec		AvailFBArea;
171609885543Smrg
17177104f784Smrg	numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
17187104f784Smrg	AvailFBArea.x1 = 0;
17197104f784Smrg	AvailFBArea.y1 = 0;
17207104f784Smrg	AvailFBArea.x2 = pScrn->virtualX;
17217104f784Smrg	AvailFBArea.y2 = numLines;
172209885543Smrg
17237104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
17247104f784Smrg		   "FrameBuffer Box: %d,%d - %d,%d\n",
17257104f784Smrg		   AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
17267104f784Smrg		   AvailFBArea.y2);
172709885543Smrg
17287104f784Smrg	xf86InitFBManager(pScreen, &AvailFBArea);
172909885543Smrg    }
173009885543Smrg
17317104f784Smrg    /* Initialize acceleration layer */
17327104f784Smrg    if (!pSmi->NoAccel) {
17337104f784Smrg	if (pSmi->useEXA && !SMI_EXAInit(pScreen))
17347104f784Smrg	    LEAVE(FALSE);
17357104f784Smrg	else if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
17367104f784Smrg	    LEAVE(FALSE);
173709885543Smrg    }
173809885543Smrg
17397104f784Smrg    /* Initialize the chosen modes */
17407104f784Smrg    if (!xf86SetDesiredModes(pScrn))
17417104f784Smrg	    LEAVE(FALSE);
174209885543Smrg
17437104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
17447104f784Smrg		   "Done writing mode.  Register dump:\n");
17457104f784Smrg    SMI_PrintRegs(pScrn);
174609885543Smrg
17477104f784Smrg    miInitializeBackingStore(pScreen);
174809885543Smrg
17497104f784Smrg#ifdef HAVE_XMODES
17507104f784Smrg    xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
17517104f784Smrg#endif
175209885543Smrg
17537104f784Smrg    /* Initialise cursor functions */
17547104f784Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
175509885543Smrg
17567104f784Smrg    /* Initialize HW cursor layer.  Must follow software cursor
17577104f784Smrg     * initialization.
17587104f784Smrg     */
17597104f784Smrg    if (pSmi->HwCursor) {
17607104f784Smrg	int	size, flags;
17617104f784Smrg
17627104f784Smrg	if (IS_MSOC(pSmi)) {
17637104f784Smrg	    size = SMI501_MAX_CURSOR;
17647104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
17657104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
17667104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
17677104f784Smrg	    if (!pSmi->Dualhead)
17687104f784Smrg		flags |= HARDWARE_CURSOR_ARGB;
17697104f784Smrg#endif
17707104f784Smrg	}
17717104f784Smrg	else {
17727104f784Smrg	    size = SMILYNX_MAX_CURSOR;
17737104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
17747104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
17757104f784Smrg		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
17767104f784Smrg		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
17777104f784Smrg		     HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
17787104f784Smrg		     HARDWARE_CURSOR_INVERT_MASK);
17797104f784Smrg	}
178009885543Smrg
17817104f784Smrg	if (!xf86_cursors_init(pScreen, size, size, flags))
17827104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
17837104f784Smrg		       "Hardware cursor initialization failed\n");
178409885543Smrg    }
178509885543Smrg
17867104f784Smrg    /* Initialise default colormap */
17877104f784Smrg    if (!miCreateDefColormap(pScreen))
17887104f784Smrg	LEAVE(FALSE);
178909885543Smrg
17907104f784Smrg    /* Initialize colormap layer.  Must follow initialization of the default
17917104f784Smrg     * colormap.  And SetGamma call, else it will load palette with solid white.
17927104f784Smrg     */
17937104f784Smrg    if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
17947104f784Smrg			     CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
17957104f784Smrg	LEAVE(FALSE);
179609885543Smrg
17977104f784Smrg    pScreen->SaveScreen = SMI_SaveScreen;
17987104f784Smrg    pSmi->CloseScreen = pScreen->CloseScreen;
17997104f784Smrg    pScreen->CloseScreen = SMI_CloseScreen;
180009885543Smrg
18017104f784Smrg    if ((IS_MSOC(pSmi) &&
18027104f784Smrg	 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
18037104f784Smrg	(!IS_MSOC(pSmi) &&
18047104f784Smrg	 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
18057104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
180609885543Smrg
18077104f784Smrg    SMI_InitVideo(pScreen);
180809885543Smrg
18097104f784Smrg    if(!xf86CrtcScreenInit(pScreen))
18107104f784Smrg	LEAVE(FALSE);
181109885543Smrg
18127104f784Smrg    /* Report any unused options (only for the first generation) */
18137104f784Smrg    if (serverGeneration == 1) {
18147104f784Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
18157104f784Smrg    }
181609885543Smrg
18177104f784Smrg    LEAVE(TRUE);
181809885543Smrg}
181909885543Smrg
182009885543Smrg/*
182109885543Smrg * This is called at the end of each server generation.  It restores the
182209885543Smrg * original (text) mode.  It should also unmap the video memory, and free any
182309885543Smrg * per-generation data allocated by the driver.  It should finish by unwrapping
182409885543Smrg * and calling the saved CloseScreen function.
182509885543Smrg */
182609885543Smrg
182709885543Smrgstatic Bool
182809885543SmrgSMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
182909885543Smrg{
18307104f784Smrg    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
18317104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
18327104f784Smrg    Bool	ret;
183309885543Smrg
18347104f784Smrg    ENTER();
183509885543Smrg
18367104f784Smrg    if (pSmi->HwCursor)
18377104f784Smrg	xf86_cursors_fini(pScreen);
18387104f784Smrg
18397104f784Smrg    if (pScrn->vtSema)
18407104f784Smrg	/* Restore console mode and unmap framebuffer */
18417104f784Smrg	SMI_LeaveVT(scrnIndex, 0);
184209885543Smrg
184309885543Smrg    if (pSmi->XAAInfoRec != NULL) {
184409885543Smrg	XAADestroyInfoRec(pSmi->XAAInfoRec);
184509885543Smrg    }
184609885543Smrg    if (pSmi->EXADriverPtr) {
184709885543Smrg	exaDriverFini(pScreen);
184809885543Smrg	pSmi->EXADriverPtr = NULL;
184909885543Smrg    }
18507104f784Smrg    if (pSmi->pVbe != NULL) {
18517104f784Smrg	vbeFree(pSmi->pVbe);
18527104f784Smrg	pSmi->pVbe = NULL;
185309885543Smrg    }
185409885543Smrg    if (pSmi->pInt10 != NULL) {
185509885543Smrg	xf86FreeInt10(pSmi->pInt10);
185609885543Smrg	pSmi->pInt10 = NULL;
185709885543Smrg    }
185809885543Smrg    if (pSmi->ptrAdaptor != NULL) {
185909885543Smrg	xfree(pSmi->ptrAdaptor);
186009885543Smrg    }
186109885543Smrg    if (pSmi->BlockHandler != NULL) {
186209885543Smrg	pScreen->BlockHandler = pSmi->BlockHandler;
186309885543Smrg    }
186409885543Smrg
186509885543Smrg    pScrn->vtSema = FALSE;
186609885543Smrg    pScreen->CloseScreen = pSmi->CloseScreen;
186709885543Smrg    ret = (*pScreen->CloseScreen)(scrnIndex, pScreen);
186809885543Smrg
18697104f784Smrg    LEAVE(ret);
187009885543Smrg}
187109885543Smrg
187209885543Smrgstatic void
187309885543SmrgSMI_FreeScreen(int scrnIndex, int flags)
187409885543Smrg{
187509885543Smrg    SMI_FreeRec(xf86Screens[scrnIndex]);
187609885543Smrg}
187709885543Smrg
187809885543Smrgstatic Bool
187909885543SmrgSMI_SaveScreen(ScreenPtr pScreen, int mode)
188009885543Smrg{
18817104f784Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
188209885543Smrg
18837104f784Smrg    ENTER();
188409885543Smrg
18857104f784Smrg    if(xf86IsUnblank(mode)){
18867104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
18877104f784Smrg    }else{
18887104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
18897104f784Smrg    }
189009885543Smrg
18917104f784Smrg    LEAVE(TRUE);
189209885543Smrg}
189309885543Smrg
189409885543Smrgvoid
189509885543SmrgSMI_AdjustFrame(int scrnIndex, int x, int y, int flags)
189609885543Smrg{
18977104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(xf86Screens[scrnIndex]);
18987104f784Smrg    xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
189909885543Smrg
19007104f784Smrg    ENTER();
190109885543Smrg
19027104f784Smrg    SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
190309885543Smrg
19047104f784Smrg    LEAVE();
190509885543Smrg}
190609885543Smrg
190709885543SmrgBool
190809885543SmrgSMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
190909885543Smrg{
191009885543Smrg    Bool ret;
19117104f784Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
19127104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
19137104f784Smrg
19147104f784Smrg    ENTER();
191509885543Smrg
19167104f784Smrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
191709885543Smrg
19187104f784Smrg    if (!pSmi->NoAccel)
19197104f784Smrg	SMI_EngineReset(pScrn);
192009885543Smrg
19217104f784Smrg    LEAVE(ret);
192209885543Smrg}
192309885543Smrg
192409885543Smrgvoid
19257104f784SmrgSMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
19267104f784Smrg		LOCO *colors, VisualPtr pVisual)
192709885543Smrg{
19287104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
19297104f784Smrg    int crtc_idx,i,j;
19307104f784Smrg
19317104f784Smrg    ENTER();
19327104f784Smrg
19337104f784Smrg    if(pScrn->bitsPerPixel == 16){
19347104f784Smrg	/* Expand the RGB 565 palette into the 256-elements LUT */
193509885543Smrg
19367104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19377104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
193809885543Smrg
19397104f784Smrg	    for(i=0; i<numColors; i++){
19407104f784Smrg		int idx = indicies[i];
194109885543Smrg
19427104f784Smrg		if(idx<32){
19437104f784Smrg		    for(j=0; j<8; j++){
19447104f784Smrg			crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
19457104f784Smrg			crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
19467104f784Smrg		    }
19477104f784Smrg		}
19487104f784Smrg
19497104f784Smrg		for(j=0; j<4; j++)
19507104f784Smrg		    crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
19517104f784Smrg	    }
19527104f784Smrg
19537104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
195409885543Smrg    }
19557104f784Smrg    }else{
19567104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19577104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
195809885543Smrg
195909885543Smrg    for(i = 0; i < numColors; i++) {
19607104f784Smrg		int idx = indicies[i];
19617104f784Smrg
19627104f784Smrg		crtcPriv->lut_r[idx] = colors[idx].red << 8;
19637104f784Smrg		crtcPriv->lut_g[idx] = colors[idx].green << 8;
19647104f784Smrg		crtcPriv->lut_b[idx] = colors[idx].blue << 8;
19657104f784Smrg	    }
19667104f784Smrg
19677104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
19687104f784Smrg	}
196909885543Smrg    }
197009885543Smrg
19717104f784Smrg    LEAVE();
197209885543Smrg}
197309885543Smrg
197409885543Smrgstatic void
197509885543SmrgSMI_DisableVideo(ScrnInfoPtr pScrn)
197609885543Smrg{
197709885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
197809885543Smrg    CARD8 tmp;
197909885543Smrg
19807104f784Smrg    if (!IS_MSOC(pSmi)) {
19817104f784Smrg	if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
19827104f784Smrg	    return;
19837104f784Smrg	pSmi->DACmask = tmp;
19847104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, 0);
19857104f784Smrg    }
198609885543Smrg}
198709885543Smrg
198809885543Smrgstatic void
198909885543SmrgSMI_EnableVideo(ScrnInfoPtr pScrn)
199009885543Smrg{
199109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
199209885543Smrg
19937104f784Smrg    if (!IS_MSOC(pSmi)) {
19947104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
19957104f784Smrg    }
199609885543Smrg}
199709885543Smrg
199809885543Smrg
199909885543Smrgvoid
200009885543SmrgSMI_EnableMmio(ScrnInfoPtr pScrn)
200109885543Smrg{
200209885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
200309885543Smrg
20047104f784Smrg    ENTER();
200509885543Smrg
20067104f784Smrg    if (!IS_MSOC(pSmi)) {
20077104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
20087104f784Smrg	CARD8 tmp;
20097104f784Smrg
20107104f784Smrg	/*
20117104f784Smrg	 * Enable chipset (seen on uninitialized secondary cards) might not be
20127104f784Smrg	 * needed once we use the VGA softbooter
20137104f784Smrg	 */
20147104f784Smrg	vgaHWSetStdFuncs(hwp);
201509885543Smrg
20167104f784Smrg	/* Enable linear mode */
20177104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20187104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20197104f784Smrg	pSmi->SR18Value = tmp;					/* PDR#521 */
20207104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11);
202109885543Smrg
20227104f784Smrg	/* Enable 2D/3D Engine and Video Processor */
20237104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20247104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20257104f784Smrg	pSmi->SR21Value = tmp;					/* PDR#521 */
20267104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03);
20277104f784Smrg    }
202809885543Smrg
20297104f784Smrg    LEAVE();
203009885543Smrg}
203109885543Smrg
203209885543Smrgvoid
203309885543SmrgSMI_DisableMmio(ScrnInfoPtr pScrn)
203409885543Smrg{
203509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
203609885543Smrg
20377104f784Smrg    ENTER();
203809885543Smrg
20397104f784Smrg    if (!IS_MSOC(pSmi)) {
20407104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
204109885543Smrg
20427104f784Smrg	vgaHWSetStdFuncs(hwp);
204309885543Smrg
20447104f784Smrg	/* Disable 2D/3D Engine and Video Processor */
20457104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20467104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value);	/* PDR#521 */
20477104f784Smrg
20487104f784Smrg	/* Disable linear mode */
20497104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20507104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value);	/* PDR#521 */
20517104f784Smrg    }
205209885543Smrg
20537104f784Smrg    LEAVE();
205409885543Smrg}
205509885543Smrg
205609885543Smrgstatic void
20577104f784SmrgSMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
20587104f784Smrg{
20597104f784Smrg    vbeInfoPtr pVbe;
20607104f784Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
20617104f784Smrg	pVbe = VBEInit(NULL, index);
20627104f784Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
20637104f784Smrg	vbeFree(pVbe);
20647104f784Smrg    }
20657104f784Smrg}
20667104f784Smrg
20677104f784Smrgstatic Bool
20687104f784SmrgSMI_HWInit(ScrnInfoPtr pScrn)
206909885543Smrg{
207009885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
207109885543Smrg
20727104f784Smrg    ENTER();
207309885543Smrg
20747104f784Smrg    if(IS_MSOC(pSmi))
20757104f784Smrg	LEAVE(SMI501_HWInit(pScrn));
20767104f784Smrg    else
20777104f784Smrg	LEAVE(SMILynx_HWInit(pScrn));
20787104f784Smrg}
207909885543Smrg
20807104f784Smrgvoid
20817104f784SmrgSMI_PrintRegs(ScrnInfoPtr pScrn)
20827104f784Smrg{
20837104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
20847104f784Smrg    int i;
208509885543Smrg
20867104f784Smrg    ENTER();
208709885543Smrg
20887104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
20897104f784Smrg		"START register dump ------------------\n");
20907104f784Smrg
20917104f784Smrg    if(IS_MSOC(pSmi))
20927104f784Smrg	SMI501_PrintRegs(pScrn);
20937104f784Smrg    else
20947104f784Smrg	SMILynx_PrintRegs(pScrn);
209509885543Smrg
209609885543Smrg
209709885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nDPR    x0       x4       x8       xC");
209809885543Smrg    for (i = 0x00; i <= 0x44; i += 4) {
209909885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
210009885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i));
210109885543Smrg    }
210209885543Smrg
210309885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nVPR    x0       x4       x8       xC");
210409885543Smrg    for (i = 0x00; i <= 0x60; i += 4) {
210509885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
210609885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i));
210709885543Smrg    }
210809885543Smrg
210909885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nCPR    x0       x4       x8       xC");
211009885543Smrg    for (i = 0x00; i <= 0x18; i += 4) {
211109885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
211209885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i));
211309885543Smrg    }
211409885543Smrg
211509885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\n");
211609885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
211709885543Smrg		"END register dump --------------------\n");
211809885543Smrg
21197104f784Smrg    LEAVE();
212009885543Smrg}
2121