smi_driver.c revision eb3dced6
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 * Internals
5909885543Smrg */
607104f784Smrgstatic Bool SMI_MapMmio(ScrnInfoPtr pScrn);
617104f784Smrgstatic Bool SMI_DetectMem(ScrnInfoPtr pScrn);
6209885543Smrgstatic void SMI_EnableMmio(ScrnInfoPtr pScrn);
6309885543Smrgstatic void SMI_DisableMmio(ScrnInfoPtr pScrn);
647104f784Smrgstatic Bool SMI_HWInit(ScrnInfoPtr pScrn);
6509885543Smrg
6609885543Smrg/*
6709885543Smrg * Forward definitions for the functions that make up the driver.
6809885543Smrg */
6909885543Smrg
7009885543Smrgstatic const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid);
7109885543Smrgstatic void SMI_Identify(int flags);
7209885543Smrgstatic Bool SMI_Probe(DriverPtr drv, int flags);
7309885543Smrgstatic Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
7409885543Smrgstatic Bool SMI_EnterVT(int scrnIndex, int flags);
7509885543Smrgstatic void SMI_LeaveVT(int scrnIndex, int flags);
7609885543Smrgstatic Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
7709885543Smrg                           char **argv);
7809885543Smrgstatic void SMI_DisableVideo(ScrnInfoPtr pScrn);
7909885543Smrgstatic void SMI_EnableVideo(ScrnInfoPtr pScrn);
8009885543Smrgstatic Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen);
8109885543Smrgstatic Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
8209885543Smrgstatic void SMI_FreeScreen(int ScrnIndex, int flags);
8309885543Smrgstatic void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
8409885543Smrgstatic void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
857104f784Smrgstatic void SMI_DetectMCLK(ScrnInfoPtr pScrn);
8609885543Smrg
877104f784Smrg/*
887104f784Smrg * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
897104f784Smrg * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion"
907104f784Smrg */
917104f784Smrg#define SILICONMOTION_NAME          "SMI"
9209885543Smrg#define SILICONMOTION_DRIVER_NAME   "siliconmotion"
937104f784Smrg#define SILICONMOTION_VERSION_NAME  PACKAGE_VERSION
947104f784Smrg#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR
957104f784Smrg#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR
967104f784Smrg#define SILICONMOTION_PATCHLEVEL    PACKAGE_VERSION_PATCHLEVEL
9709885543Smrg#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
9809885543Smrg                                      (SILICONMOTION_VERSION_MINOR << 16) | \
9909885543Smrg                                      (SILICONMOTION_PATCHLEVEL))
10009885543Smrg
1017104f784Smrg#if SMI_DEBUG
1027104f784Smrgint smi_indent = 1;
1037104f784Smrg#endif
1047104f784Smrg
1057104f784Smrg/* for dualhead */
1067104f784Smrgint gSMIEntityIndex = -1;
1077104f784Smrg
10809885543Smrg/*
10909885543Smrg * This contains the functions needed by the server after loading the
11009885543Smrg * driver module.  It must be supplied, and gets added the driver list by
11109885543Smrg * the Module Setup funtion in the dynamic case.  In the static case a
11209885543Smrg * reference to this is compiled in, and this requires that the name of
11309885543Smrg * this DriverRec be an upper-case version of the driver name.
11409885543Smrg */
11509885543Smrg
11609885543Smrg_X_EXPORT DriverRec SILICONMOTION =
11709885543Smrg{
11809885543Smrg    SILICONMOTION_DRIVER_VERSION,
11909885543Smrg    SILICONMOTION_DRIVER_NAME,
12009885543Smrg    SMI_Identify,
12109885543Smrg    SMI_Probe,
12209885543Smrg    SMI_AvailableOptions,
12309885543Smrg    NULL,
12409885543Smrg    0
12509885543Smrg};
12609885543Smrg
12709885543Smrg/* Supported chipsets */
12809885543Smrgstatic SymTabRec SMIChipsets[] =
12909885543Smrg{
13009885543Smrg    { PCI_CHIP_SMI910, "Lynx"    },
13109885543Smrg    { PCI_CHIP_SMI810, "LynxE"   },
13209885543Smrg    { PCI_CHIP_SMI820, "Lynx3D"  },
13309885543Smrg    { PCI_CHIP_SMI710, "LynxEM"  },
13409885543Smrg    { PCI_CHIP_SMI712, "LynxEM+" },
13509885543Smrg    { PCI_CHIP_SMI720, "Lynx3DM" },
13609885543Smrg    { PCI_CHIP_SMI731, "Cougar3DR" },
1377104f784Smrg    { PCI_CHIP_SMI501, "MSOC"	 },
13809885543Smrg    { -1,             NULL      }
13909885543Smrg};
14009885543Smrg
14109885543Smrgstatic PciChipsets SMIPciChipsets[] =
14209885543Smrg{
1437104f784Smrg    /* numChipset,	PciID,			Resource */
14409885543Smrg    { PCI_CHIP_SMI910,	PCI_CHIP_SMI910,	RES_SHARED_VGA },
14509885543Smrg    { PCI_CHIP_SMI810,	PCI_CHIP_SMI810,	RES_SHARED_VGA },
14609885543Smrg    { PCI_CHIP_SMI820,	PCI_CHIP_SMI820,	RES_SHARED_VGA },
14709885543Smrg    { PCI_CHIP_SMI710,	PCI_CHIP_SMI710,	RES_SHARED_VGA },
14809885543Smrg    { PCI_CHIP_SMI712,	PCI_CHIP_SMI712,	RES_SHARED_VGA },
14909885543Smrg    { PCI_CHIP_SMI720,	PCI_CHIP_SMI720,	RES_SHARED_VGA },
15009885543Smrg    { PCI_CHIP_SMI731,	PCI_CHIP_SMI731,	RES_SHARED_VGA },
1517104f784Smrg    { PCI_CHIP_SMI501,	PCI_CHIP_SMI501,	RES_UNDEFINED  },
1527104f784Smrg    { -1,		-1,			RES_UNDEFINED  }
15309885543Smrg};
15409885543Smrg
15509885543Smrgtypedef enum
15609885543Smrg{
15709885543Smrg    OPTION_PCI_BURST,
15809885543Smrg    OPTION_PCI_RETRY,
15909885543Smrg    OPTION_NOACCEL,
16009885543Smrg    OPTION_MCLK,
1617104f784Smrg    OPTION_MXCLK,
16209885543Smrg    OPTION_SWCURSOR,
16309885543Smrg    OPTION_HWCURSOR,
16409885543Smrg    OPTION_VIDEOKEY,
16509885543Smrg    OPTION_BYTESWAP,
16609885543Smrg    /* CZ 26.10.2001: interlaced video */
16709885543Smrg    OPTION_INTERLACED,
16809885543Smrg    /* end CZ */
16909885543Smrg    OPTION_USEBIOS,
17009885543Smrg    OPTION_DUALHEAD,
17109885543Smrg    OPTION_ACCELMETHOD,
1727104f784Smrg    OPTION_PANEL_SIZE,
1737104f784Smrg    OPTION_USE_FBDEV,
1747104f784Smrg    OPTION_CSCVIDEO,
17509885543Smrg    NUMBER_OF_OPTIONS
17609885543Smrg} SMIOpts;
17709885543Smrg
17809885543Smrgstatic const OptionInfoRec SMIOptions[] =
17909885543Smrg{
1807104f784Smrg    { OPTION_PCI_BURST,	     "pci_burst",	  OPTV_BOOLEAN, {0}, TRUE },
1817104f784Smrg    { OPTION_PCI_RETRY,	     "pci_retry",	  OPTV_BOOLEAN, {0}, TRUE },
18209885543Smrg    { OPTION_NOACCEL,	     "NoAccel",		  OPTV_BOOLEAN, {0}, FALSE },
1837104f784Smrg    { OPTION_MCLK,	     "MCLK",		  OPTV_FREQ,	{0}, FALSE },
1847104f784Smrg    { OPTION_MXCLK,	     "MXCLK",		  OPTV_FREQ,	{0}, FALSE },
1857104f784Smrg    { OPTION_HWCURSOR,	     "HWCursor",	  OPTV_BOOLEAN, {0}, TRUE },
18609885543Smrg    { OPTION_SWCURSOR,	     "SWCursor",	  OPTV_BOOLEAN, {0}, FALSE },
18709885543Smrg    { OPTION_VIDEOKEY,	     "VideoKey",	  OPTV_INTEGER, {0}, FALSE },
18809885543Smrg    { OPTION_BYTESWAP,	     "ByteSwap",	  OPTV_BOOLEAN, {0}, FALSE },
18909885543Smrg    /* CZ 26.10.2001: interlaced video */
1907104f784Smrg    { OPTION_INTERLACED,     "Interlaced",        OPTV_BOOLEAN, {0}, FALSE },
19109885543Smrg    /* end CZ */
19209885543Smrg    { OPTION_USEBIOS,	     "UseBIOS",		  OPTV_BOOLEAN,	{0}, FALSE },
1937104f784Smrg    { OPTION_DUALHEAD,	     "Dualhead",	  OPTV_BOOLEAN,	{0}, TRUE },
19409885543Smrg    { OPTION_ACCELMETHOD,    "AccelMethod",       OPTV_STRING,  {0}, FALSE },
1957104f784Smrg    { OPTION_PANEL_SIZE,     "PanelSize",	  OPTV_ANYSTR,	{0}, FALSE },
1967104f784Smrg    { OPTION_USE_FBDEV,	     "UseFBDev",	  OPTV_BOOLEAN,	{0}, FALSE },
1977104f784Smrg    { OPTION_CSCVIDEO,	     "CSCVideo",	  OPTV_BOOLEAN, {0}, TRUE },
19809885543Smrg    { -1,		     NULL,		  OPTV_NONE,	{0}, FALSE }
19909885543Smrg};
20009885543Smrg
20109885543Smrg#ifdef XFree86LOADER
20209885543Smrg
20309885543Smrgstatic MODULESETUPPROTO(siliconmotionSetup);
20409885543Smrg
20509885543Smrgstatic XF86ModuleVersionInfo SMIVersRec =
20609885543Smrg{
20709885543Smrg    "siliconmotion",
20809885543Smrg    MODULEVENDORSTRING,
20909885543Smrg    MODINFOSTRING1,
21009885543Smrg    MODINFOSTRING2,
21109885543Smrg    XORG_VERSION_CURRENT,
21209885543Smrg    SILICONMOTION_VERSION_MAJOR,
21309885543Smrg    SILICONMOTION_VERSION_MINOR,
21409885543Smrg    SILICONMOTION_PATCHLEVEL,
21509885543Smrg    ABI_CLASS_VIDEODRV,
21609885543Smrg    ABI_VIDEODRV_VERSION,
21709885543Smrg    MOD_CLASS_VIDEODRV,
21809885543Smrg    {0, 0, 0, 0}
21909885543Smrg};
22009885543Smrg
22109885543Smrg/*
22209885543Smrg * This is the module init data for XFree86 modules.
22309885543Smrg *
22409885543Smrg * Its name has to be the driver name followed by ModuleData.
22509885543Smrg */
22609885543Smrg_X_EXPORT XF86ModuleData siliconmotionModuleData =
22709885543Smrg{
22809885543Smrg    &SMIVersRec,
22909885543Smrg    siliconmotionSetup,
23009885543Smrg    NULL
23109885543Smrg};
23209885543Smrg
23309885543Smrgstatic pointer
23409885543SmrgsiliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin)
23509885543Smrg{
23609885543Smrg    static Bool setupDone = FALSE;
23709885543Smrg
23809885543Smrg    if (!setupDone) {
23909885543Smrg	setupDone = TRUE;
24009885543Smrg	xf86AddDriver(&SILICONMOTION, module, 0);
24109885543Smrg
24209885543Smrg	/*
24309885543Smrg	 * The return value must be non-NULL on success even though there
24409885543Smrg	 * is no TearDownProc.
24509885543Smrg	 */
24609885543Smrg	return (pointer) 1;
24709885543Smrg
24809885543Smrg    } else {
24909885543Smrg	if (errmaj) {
25009885543Smrg	    *errmaj = LDR_ONCEONLY;
25109885543Smrg	}
25209885543Smrg	return NULL;
25309885543Smrg    }
25409885543Smrg}
25509885543Smrg
25609885543Smrg#endif /* XFree86LOADER */
25709885543Smrg
25809885543Smrgstatic Bool
25909885543SmrgSMI_GetRec(ScrnInfoPtr pScrn)
26009885543Smrg{
2617104f784Smrg    ENTER();
26209885543Smrg
26309885543Smrg    /*
26409885543Smrg     * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
26509885543Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
26609885543Smrg     * the allocation has already been done.
26709885543Smrg     */
26809885543Smrg    if (pScrn->driverPrivate == NULL) {
26909885543Smrg	pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
27009885543Smrg    }
27109885543Smrg
2727104f784Smrg    LEAVE(TRUE);
27309885543Smrg}
27409885543Smrg
27509885543Smrgstatic void
27609885543SmrgSMI_FreeRec(ScrnInfoPtr pScrn)
27709885543Smrg{
2787104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
27909885543Smrg
2807104f784Smrg    ENTER();
2817104f784Smrg
2827104f784Smrg    if (pSmi) {
2837b58d2e0Smrg	free(pSmi->save);
2847b58d2e0Smrg	free(pSmi->mode);
2857b58d2e0Smrg	free(pScrn->driverPrivate);
28609885543Smrg	pScrn->driverPrivate = NULL;
28709885543Smrg    }
28809885543Smrg
2897104f784Smrg    LEAVE();
29009885543Smrg}
29109885543Smrg
29209885543Smrgstatic const OptionInfoRec *
29309885543SmrgSMI_AvailableOptions(int chipid, int busid)
29409885543Smrg{
2957104f784Smrg    ENTER();
2967104f784Smrg
2977104f784Smrg    LEAVE(SMIOptions);
29809885543Smrg}
29909885543Smrg
30009885543Smrgstatic void
30109885543SmrgSMI_Identify(int flags)
30209885543Smrg{
3037104f784Smrg    ENTER();
30409885543Smrg
30509885543Smrg    xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
30609885543Smrg		SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
30709885543Smrg		SMIChipsets);
30809885543Smrg
3097104f784Smrg    LEAVE();
31009885543Smrg}
31109885543Smrg
31209885543Smrgstatic Bool
31309885543SmrgSMI_Probe(DriverPtr drv, int flags)
31409885543Smrg{
31509885543Smrg    int i;
31609885543Smrg    GDevPtr *devSections;
31709885543Smrg    int *usedChips;
31809885543Smrg    int numDevSections;
31909885543Smrg    int numUsed;
32009885543Smrg    Bool foundScreen = FALSE;
32109885543Smrg
3227104f784Smrg    ENTER();
32309885543Smrg
32409885543Smrg    numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
32509885543Smrg
3267104f784Smrg    if (numDevSections <= 0)
32709885543Smrg	/* There's no matching device section in the config file, so quit now. */
3287104f784Smrg	LEAVE(FALSE);
32909885543Smrg
3307104f784Smrg#ifndef XSERVER_LIBPCIACCESS
3317104f784Smrg    if (xf86GetPciVideoInfo() == NULL)
3327104f784Smrg	LEAVE(FALSE);
3337104f784Smrg#endif
33409885543Smrg
33509885543Smrg    numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
33609885543Smrg				    SMIChipsets, SMIPciChipsets, devSections,
33709885543Smrg				    numDevSections, drv, &usedChips);
33809885543Smrg
33909885543Smrg    /* Free it since we don't need that list after this */
3407b58d2e0Smrg    free(devSections);
3417104f784Smrg    if (numUsed <= 0)
3427104f784Smrg	LEAVE(FALSE);
3437104f784Smrg
3447104f784Smrg    if (flags & PROBE_DETECT)
3457104f784Smrg	foundScreen = TRUE;
3467104f784Smrg    else {
3477104f784Smrg	ScrnInfoPtr	pScrn;
3487104f784Smrg	EntityInfoPtr	pEnt;
34909885543Smrg
35009885543Smrg	for (i = 0; i < numUsed; i++) {
3517104f784Smrg	    if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
3527104f784Smrg					     SMIPciChipsets, NULL,
3537104f784Smrg					     NULL, NULL, NULL, NULL))) {
3547104f784Smrg		pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
3557104f784Smrg		pScrn->driverName    = SILICONMOTION_DRIVER_NAME;
3567104f784Smrg		pScrn->name	     = SILICONMOTION_NAME;
3577104f784Smrg		pScrn->Probe	     = SMI_Probe;
3587104f784Smrg		pScrn->PreInit	     = SMI_PreInit;
3597104f784Smrg		pScrn->ScreenInit    = SMI_ScreenInit;
3607104f784Smrg		pScrn->SwitchMode    = SMI_SwitchMode;
3617104f784Smrg		pScrn->AdjustFrame   = SMI_AdjustFrame;
3627104f784Smrg
3637104f784Smrg		if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
3647104f784Smrg			pScrn->EnterVT   = SMI_EnterVT;
3657104f784Smrg			pScrn->LeaveVT   = SMI_LeaveVT;
3667b58d2e0Smrg		    free(pEnt);
3677104f784Smrg		}
3687104f784Smrg		pScrn->FreeScreen    = SMI_FreeScreen;
3697104f784Smrg		foundScreen	     = TRUE;
3707104f784Smrg	    }
37109885543Smrg	}
37209885543Smrg    }
3737b58d2e0Smrg    free(usedChips);
37409885543Smrg
3757104f784Smrg    LEAVE(foundScreen);
37609885543Smrg}
37709885543Smrg
37809885543Smrgstatic Bool
37909885543SmrgSMI_PreInit(ScrnInfoPtr pScrn, int flags)
38009885543Smrg{
38109885543Smrg    EntityInfoPtr pEnt;
38209885543Smrg    SMIPtr pSmi;
38309885543Smrg    MessageType from;
38409885543Smrg    vgaHWPtr hwp;
38509885543Smrg
3867104f784Smrg    ENTER();
38709885543Smrg
38809885543Smrg    /* Ignoring the Type list for now.  It might be needed when multiple cards
38909885543Smrg     * are supported.
39009885543Smrg     */
3917104f784Smrg    if (pScrn->numEntities > 1)
3927104f784Smrg	LEAVE(FALSE);
39309885543Smrg
3947104f784Smrg    /* Allocate the SMIRec driverPrivate */
3957104f784Smrg    if (!SMI_GetRec(pScrn))
3967104f784Smrg	LEAVE(FALSE);
3977104f784Smrg    pSmi = SMIPTR(pScrn);
39809885543Smrg
3997104f784Smrg    /* Find the PCI slot for this screen */
4007104f784Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
40109885543Smrg
4027104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
4037104f784Smrg    pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
4047104f784Smrg
4057104f784Smrg    if (IS_MSOC(pSmi)) {
4067104f784Smrg	pSmi->Save = SMI501_Save;
4077104f784Smrg	pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
4087104f784Smrg	pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
4097104f784Smrg    }
4107104f784Smrg    else {
4117104f784Smrg	pSmi->Save = SMILynx_Save;
4127104f784Smrg	pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
4137104f784Smrg	pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
41409885543Smrg    }
41509885543Smrg
4167104f784Smrg    if (flags & PROBE_DETECT) {
4177104f784Smrg	if (!IS_MSOC(pSmi))
4187104f784Smrg	    SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
4197104f784Smrg	LEAVE(TRUE);
42009885543Smrg    }
4217104f784Smrg
422b698ba48Smrg    if (pEnt->location.type != BUS_PCI) {
4237b58d2e0Smrg	free(pEnt);
4247104f784Smrg	SMI_FreeRec(pScrn);
4257104f784Smrg	LEAVE(FALSE);
4267104f784Smrg    }
4277104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
42809885543Smrg
42909885543Smrg    /* Set pScrn->monitor */
43009885543Smrg    pScrn->monitor = pScrn->confScreen->monitor;
43109885543Smrg
4327104f784Smrg    if (!IS_MSOC(pSmi)) {
4337104f784Smrg	/* The vgahw module should be loaded here when needed */
4347104f784Smrg	if (!xf86LoadSubModule(pScrn, "vgahw"))
4357104f784Smrg	    LEAVE(FALSE);
4367104f784Smrg
4377104f784Smrg	/*
4387104f784Smrg	 * Allocate a vgaHWRec
4397104f784Smrg	 */
4407104f784Smrg	if (!vgaHWGetHWRec(pScrn))
4417104f784Smrg	    LEAVE(FALSE);
4427104f784Smrg
4437104f784Smrg	hwp = VGAHWPTR(pScrn);
4447104f784Smrg	pSmi->PIOBase = hwp->PIOOffset;
4457104f784Smrg
4467104f784Smrg	xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
4477104f784Smrg		       "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET,
4487104f784Smrg		       hwp->IOBase, hwp->MMIOBase);
4497104f784Smrg    }
4507104f784Smrg
45109885543Smrg    /*
45209885543Smrg     * The first thing we should figure out is the depth, bpp, etc.
45309885543Smrg     */
4547104f784Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
4557104f784Smrg	LEAVE(FALSE);
45609885543Smrg
45709885543Smrg    /* Check that the returned depth is one we support */
4587104f784Smrg    if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) {
45909885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
46009885543Smrg		   "Given depth (%d) is not supported by this driver\n",
46109885543Smrg		   pScrn->depth);
4627104f784Smrg	LEAVE(FALSE);
4637104f784Smrg    }
4647104f784Smrg
4657104f784Smrg
4667104f784Smrg    if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
4677104f784Smrg       pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
4687104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4697104f784Smrg		   "Given bpp (%d) is not supported by this driver\n",
4707104f784Smrg		   pScrn->bitsPerPixel);
4717104f784Smrg	LEAVE(FALSE);
47209885543Smrg    }
47309885543Smrg
47409885543Smrg    xf86PrintDepthBpp(pScrn);
47509885543Smrg
4762ec8c4b4Smrg    pSmi->Bpp = pScrn->bitsPerPixel >> 3;
4772ec8c4b4Smrg
47809885543Smrg    /*
47909885543Smrg     * This must happen after pScrn->display has been set because
48009885543Smrg     * xf86SetWeight references it.
48109885543Smrg     */
48209885543Smrg    if (pScrn->depth > 8) {
48309885543Smrg	/* The defaults are OK for us */
48409885543Smrg	rgb zeros = {0, 0, 0};
4857104f784Smrg#if __BYTE_ORDER == __BIG_ENDIAN
4867104f784Smrg	rgb masks = {0xff00,0xff0000,0xff000000};
4877104f784Smrg#else
4887104f784Smrg	rgb masks = {0, 0, 0};
4897104f784Smrg#endif
49009885543Smrg
4917104f784Smrg	if (!xf86SetWeight(pScrn, zeros, masks))
4927104f784Smrg	    LEAVE(FALSE);
49309885543Smrg    }
49409885543Smrg
4957104f784Smrg    if (!xf86SetDefaultVisual(pScrn, -1))
4967104f784Smrg	LEAVE(FALSE);
49709885543Smrg
49809885543Smrg    /* We don't currently support DirectColor at > 8bpp */
4997104f784Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
50009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) "
50109885543Smrg		   "is not supported at depth %d\n",
50209885543Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
5037104f784Smrg	LEAVE(FALSE);
50409885543Smrg    }
50509885543Smrg
50609885543Smrg    /* We use a programmable clock */
50709885543Smrg    pScrn->progClock = TRUE;
50809885543Smrg
50909885543Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
51009885543Smrg    xf86CollectOptions(pScrn, NULL);
51109885543Smrg
51209885543Smrg    /* Set the bits per RGB for 8bpp mode */
5137104f784Smrg    if (pScrn->depth == 8){
5147104f784Smrg	pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
5157104f784Smrg    }else if(pScrn->depth == 16){
5167104f784Smrg	/* Use 8 bit LUT for gamma correction*/
5177104f784Smrg	pScrn->rgbBits = 8;
51809885543Smrg    }
51909885543Smrg
52009885543Smrg    /* Process the options */
5217b58d2e0Smrg    if (!(pSmi->Options = malloc(sizeof(SMIOptions))))
5227104f784Smrg	LEAVE(FALSE);
5237104f784Smrg
52409885543Smrg    memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
52509885543Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
52609885543Smrg
5277104f784Smrg    /* Enable pci burst by default */
5287104f784Smrg    from = X_DEFAULT;
5297104f784Smrg    pSmi->PCIBurst = TRUE;
5307104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst))
5317104f784Smrg	from = X_CONFIG;
5327104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n",
5337104f784Smrg	       pSmi->PCIBurst ? "en" : "dis");
53409885543Smrg
5357104f784Smrg    /* Pci retry enabled by default if pci burst also enabled */
5367104f784Smrg    from = X_DEFAULT;
5377104f784Smrg    pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE;
5387104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) {
5397104f784Smrg	from = X_CONFIG;
5407104f784Smrg	if (pSmi->PCIRetry && !pSmi->PCIBurst) {
5417104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5427104f784Smrg		       "\"pci_retry\" option requires \"pci_burst\".\n");
5437104f784Smrg	    pSmi->PCIRetry = FALSE;
54409885543Smrg	}
54509885543Smrg    }
5467104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n",
5477104f784Smrg	       pSmi->PCIRetry ? "en" : "dis");
54809885543Smrg
54909885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) {
55009885543Smrg	pSmi->NoAccel = TRUE;
55109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
55209885543Smrg		   "disabled\n");
55309885543Smrg    } else {
55409885543Smrg	pSmi->NoAccel = FALSE;
55509885543Smrg    }
55609885543Smrg
5577104f784Smrg    if (IS_MSOC(pSmi)) {
5587104f784Smrg	from = X_DEFAULT;
5597104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
5607104f784Smrg	    from = X_CONFIG;
5617104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n",
5627104f784Smrg		   pSmi->UseFBDev ? "enabled" : "disabled");
5637104f784Smrg    }
5647104f784Smrg
5657104f784Smrg    from = X_CONFIG;
5667104f784Smrg    pSmi->HwCursor = TRUE;
5677104f784Smrg    /* SWCursor overrides HWCusor if both specified */
5687104f784Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
5697104f784Smrg	pSmi->HwCursor = FALSE;
5707104f784Smrg    else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
5717104f784Smrg	from = X_DEFAULT;
57209885543Smrg
5737104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
5747104f784Smrg	       pSmi->HwCursor ? "Hard" : "Soft");
57509885543Smrg
57609885543Smrg    if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
57709885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
57809885543Smrg		   "0x%08X\n", pSmi->videoKey);
57909885543Smrg    } else {
58009885543Smrg	pSmi->videoKey = (1 << pScrn->offset.red) |
58109885543Smrg			 (1 << pScrn->offset.green) |
58209885543Smrg			 (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
58309885543Smrg			 << pScrn->offset.blue);
58409885543Smrg    }
58509885543Smrg
58609885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) {
58709885543Smrg	pSmi->ByteSwap = TRUE;
58809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
58909885543Smrg    } else {
59009885543Smrg	pSmi->ByteSwap = FALSE;
59109885543Smrg    }
59209885543Smrg
59309885543Smrg    /* CZ 26.10.2001: interlaced video */
59409885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) {
59509885543Smrg	pSmi->interlaced = TRUE;
59609885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
59709885543Smrg    } else {
59809885543Smrg	pSmi->interlaced = FALSE;
59909885543Smrg    }
60009885543Smrg    /* end CZ */
60109885543Smrg
6027104f784Smrg    if (IS_MSOC(pSmi))
6037104f784Smrg	pSmi->useBIOS = FALSE;
6047104f784Smrg    else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) {
60509885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
60609885543Smrg		   pSmi->useBIOS ? "enabled" : "disabled");
6077104f784Smrg    }
6087104f784Smrg    else if(pSmi->Chipset == SMI_LYNX3DM){
6097104f784Smrg	/* Default to UseBIOS disabled. */
6107104f784Smrg	pSmi->useBIOS = FALSE;
6117104f784Smrg    }
6127104f784Smrg    else {
61309885543Smrg	/* Default to UseBIOS enabled. */
61409885543Smrg	pSmi->useBIOS = TRUE;
61509885543Smrg    }
61609885543Smrg
6177104f784Smrg    if (pSmi->useBIOS) {
6187104f784Smrg	if (xf86LoadSubModule(pScrn,"int10")) {
6197104f784Smrg	    pSmi->pInt10 = xf86InitInt10(pEnt->index);
6207104f784Smrg	}
62109885543Smrg
6227104f784Smrg	if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
6237104f784Smrg	    pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
6247104f784Smrg	}
62509885543Smrg
6267104f784Smrg	if(!pSmi->pVbe){
6277104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n");
6287104f784Smrg	    pSmi->useBIOS = FALSE;
6297104f784Smrg	}
63009885543Smrg    }
63109885543Smrg
632b698ba48Smrg#ifndef XSERVER_LIBPCIACCESS
63309885543Smrg    xf86RegisterResources(pEnt->index, NULL, ResExclusive);
634b698ba48Smrg#endif
63509885543Smrg    /*
63609885543Smrg     * Set the Chipset and ChipRev, allowing config file entries to
63709885543Smrg     * override.
63809885543Smrg     */
63909885543Smrg    if (pEnt->device->chipset && *pEnt->device->chipset) {
64009885543Smrg	pScrn->chipset = pEnt->device->chipset;
64109885543Smrg	pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
64209885543Smrg	from = X_CONFIG;
6437104f784Smrg    }
6447104f784Smrg    else if (pEnt->device->chipID >= 0) {
64509885543Smrg	pSmi->Chipset = pEnt->device->chipID;
64609885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
64709885543Smrg	from = X_CONFIG;
64809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
64909885543Smrg		   pSmi->Chipset);
6507104f784Smrg    }
6517104f784Smrg    else {
65209885543Smrg	from = X_PROBED;
6537104f784Smrg	pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
65409885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
65509885543Smrg    }
65609885543Smrg
65709885543Smrg    if (pEnt->device->chipRev >= 0) {
65809885543Smrg	pSmi->ChipRev = pEnt->device->chipRev;
65909885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
66009885543Smrg		   pSmi->ChipRev);
66109885543Smrg    }
6627104f784Smrg    else
6637104f784Smrg        pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo);
6647b58d2e0Smrg    free(pEnt);
66509885543Smrg
66609885543Smrg    /*
66709885543Smrg     * This shouldn't happen because such problems should be caught in
66809885543Smrg     * SMI_Probe(), but check it just in case.
66909885543Smrg     */
67009885543Smrg    if (pScrn->chipset == NULL) {
67109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
67209885543Smrg				"recognised\n", pSmi->Chipset);
6737104f784Smrg	LEAVE(FALSE);
67409885543Smrg    }
67509885543Smrg
67609885543Smrg    if (pSmi->Chipset < 0) {
67709885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
67809885543Smrg		   "recognised\n", pScrn->chipset);
6797104f784Smrg	LEAVE(FALSE);
68009885543Smrg    }
68109885543Smrg
68209885543Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
68309885543Smrg
6847104f784Smrg#ifndef XSERVER_LIBPCIACCESS
68509885543Smrg    pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
68609885543Smrg		   	  pSmi->PciInfo->func);
6877104f784Smrg#endif
68809885543Smrg
6897104f784Smrg    from = X_DEFAULT;
6907104f784Smrg    if(pSmi->Chipset == SMI_LYNX3DM &&
6917104f784Smrg       pScrn->bitsPerPixel == 16)
69209885543Smrg	pSmi->Dualhead = TRUE;
6937104f784Smrg    else
6947104f784Smrg	pSmi->Dualhead = FALSE;
6957104f784Smrg
6967104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead))
6977104f784Smrg	from = X_CONFIG;
6987104f784Smrg
6997104f784Smrg    if (IS_MSOC(pSmi)) {
7007104f784Smrg	pSmi->lcd = TRUE;
7017104f784Smrg	if (pSmi->Dualhead && pSmi->UseFBDev) {
7027104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7037104f784Smrg		       "Dual head disabled in fbdev mode\n");
7047104f784Smrg	    pSmi->Dualhead = FALSE;
7057104f784Smrg	}
7067104f784Smrg	/* FIXME Randr cursor code only works properly when argb cursors
7077104f784Smrg	 * are also supported.
7087104f784Smrg	 * FIXME This probably is a randr cursor bug, and since access to
7097104f784Smrg	 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor
7107104f784Smrg	 * field is not available, one cannot easily workaround the problem,
7117104f784Smrg	 * so, just disable it...
7127104f784Smrg	 * TODO Check with a X Server newer then 1.4.0.90 (that is being
7137104f784Smrg	 * used in the 502 OEM image).
7147104f784Smrg	 * */
7157104f784Smrg	if (pSmi->Dualhead && pSmi->HwCursor) {
7167104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7177104f784Smrg		       "HW Cursor disabled in dual head mode\n");
7187104f784Smrg	    pSmi->HwCursor = FALSE;
7197104f784Smrg	}
7207104f784Smrg    }
7217104f784Smrg    else if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
7227104f784Smrg	/* tweak options for dualhead */
7237104f784Smrg	if (pSmi->Dualhead) {
7247104f784Smrg	    pSmi->useBIOS = FALSE;
7257104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n");
7267104f784Smrg	    pSmi->HwCursor = FALSE;
7277104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n");
7287104f784Smrg	    if (pScrn->bitsPerPixel != 16) {
7297104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at "
7307104f784Smrg			   "depth 16\n");
7317104f784Smrg		LEAVE(FALSE);
7327104f784Smrg	    }
7337104f784Smrg	}
73409885543Smrg    }
7357104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n",
7367104f784Smrg	       pSmi->Dualhead ? "en" : "dis");
73709885543Smrg
7387104f784Smrg    if (!pSmi->NoAccel) {
7397104f784Smrg	char *strptr;
7407104f784Smrg
7417104f784Smrg	from = X_DEFAULT;
7427104f784Smrg	if ((strptr = (char *)xf86GetOptValString(pSmi->Options,
7437104f784Smrg						  OPTION_ACCELMETHOD))) {
7447104f784Smrg	    if (!xf86NameCmp(strptr,"XAA")) {
7457104f784Smrg		from = X_CONFIG;
7467104f784Smrg		pSmi->useEXA = FALSE;
7477104f784Smrg	    } else if(!xf86NameCmp(strptr,"EXA")) {
7487104f784Smrg		from = X_CONFIG;
7497104f784Smrg		pSmi->useEXA = TRUE;
7507104f784Smrg	    }
75109885543Smrg	}
7527104f784Smrg
7537104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
7547104f784Smrg		pSmi->useEXA ? "EXA" : "XAA");
75509885543Smrg    }
75609885543Smrg
7577104f784Smrg    if (IS_MSOC(pSmi)) {
7587104f784Smrg	pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead;
7597104f784Smrg	from = X_DEFAULT;
7607104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) {
7617104f784Smrg	    from = X_CONFIG;
7627104f784Smrg
7637104f784Smrg	    /* FIXME */
7647104f784Smrg	    if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) {
7657104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
7667104f784Smrg			   "CSCVideo requires XAA or EXA in single head mode.\n");
7677104f784Smrg		pSmi->CSCVideo = FALSE;
7687104f784Smrg	    }
7697104f784Smrg	}
77009885543Smrg
7717104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n",
7727104f784Smrg		   pSmi->CSCVideo ? "en" : "dis");
7737104f784Smrg    }
77409885543Smrg
7757104f784Smrg    SMI_MapMmio(pScrn);
7767104f784Smrg    SMI_DetectMem(pScrn);
7777104f784Smrg    SMI_MapMem(pScrn);
7787104f784Smrg    SMI_DisableVideo(pScrn);
77909885543Smrg
78009885543Smrg    /* detect the panel size */
78109885543Smrg    SMI_DetectPanelSize(pScrn);
78209885543Smrg
7837104f784Smrg    if(!IS_MSOC(pSmi)){
7847104f784Smrg	if (xf86LoadSubModule(pScrn, "i2c")) {
7857104f784Smrg	    SMI_I2CInit(pScrn);
7867104f784Smrg	}
7872ec8c4b4Smrg	xf86LoadSubModule(pScrn, "ddc");
78809885543Smrg    }
78909885543Smrg
79009885543Smrg    /*
79109885543Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
79209885543Smrg     */
79309885543Smrg    {
79409885543Smrg	Gamma zeros = { 0.0, 0.0, 0.0 };
79509885543Smrg
79609885543Smrg	if (!xf86SetGamma(pScrn, zeros)) {
79709885543Smrg	    SMI_EnableVideo(pScrn);
79809885543Smrg	    SMI_UnmapMem(pScrn);
7997104f784Smrg	    LEAVE(FALSE);
80009885543Smrg	}
80109885543Smrg    }
80209885543Smrg
8037104f784Smrg    SMI_DetectMCLK(pScrn);
80409885543Smrg
80509885543Smrg    /*
80609885543Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
80709885543Smrg     * and what sort of modes they can be used for.
80809885543Smrg     */
8097104f784Smrg    pSmi->clockRange.next = NULL;
8107104f784Smrg    pSmi->clockRange.minClock = 20000;
81109885543Smrg
8127104f784Smrg    if (SMI_LYNXM_SERIES(pSmi->Chipset) ||
8137104f784Smrg	IS_MSOC(pSmi))
8147104f784Smrg	pSmi->clockRange.maxClock = 200000;
81509885543Smrg    else
8167104f784Smrg        pSmi->clockRange.maxClock = 135000;
81709885543Smrg
8187104f784Smrg    pSmi->clockRange.clockIndex = -1;
8197104f784Smrg    pSmi->clockRange.interlaceAllowed = FALSE;
8207104f784Smrg    pSmi->clockRange.doubleScanAllowed = FALSE;
82109885543Smrg
8227104f784Smrg    if(!SMI_CrtcPreInit(pScrn))
8237104f784Smrg	LEAVE(FALSE);
8247104f784Smrg
8257104f784Smrg    if(!SMI_OutputPreInit(pScrn))
8267104f784Smrg	LEAVE(FALSE);
8277104f784Smrg
8287104f784Smrg    /* Only allow growing the screen dimensions if EXA is being used */
8297104f784Smrg    if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){
83009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
8312ec8c4b4Smrg
8322ec8c4b4Smrg	SMI_EnableVideo(pScrn);
8332ec8c4b4Smrg	SMI_UnmapMem(pScrn);
8347104f784Smrg	LEAVE(FALSE);
83509885543Smrg    }
83609885543Smrg
8372ec8c4b4Smrg    /* Ensure that the framebuffer size just set fits in video memory. */
8382ec8c4b4Smrg    {
8392ec8c4b4Smrg	int aligned_pitch = (pScrn->virtualX*pSmi->Bpp + 15) & ~15;
8402ec8c4b4Smrg
8412ec8c4b4Smrg	if(aligned_pitch * pScrn->virtualY > pSmi->FBReserved){
8422ec8c4b4Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video memory "
8432ec8c4b4Smrg		       "for the configured screen size (%dx%d) and color depth.\n",
8442ec8c4b4Smrg                       pScrn->virtualX, pScrn->virtualY);
8452ec8c4b4Smrg
8462ec8c4b4Smrg	    SMI_EnableVideo(pScrn);
8472ec8c4b4Smrg	    SMI_UnmapMem(pScrn);
8482ec8c4b4Smrg	    LEAVE(FALSE);
8492ec8c4b4Smrg	}
8502ec8c4b4Smrg    }
8512ec8c4b4Smrg
85209885543Smrg
8537104f784Smrg    SMI_EnableVideo(pScrn);
8547104f784Smrg    SMI_UnmapMem(pScrn);
8557104f784Smrg
8567104f784Smrg    if(pSmi->pVbe){
8577104f784Smrg       vbeFree(pSmi->pVbe);
8587104f784Smrg       pSmi->pVbe = NULL;
8597104f784Smrg    }
8607104f784Smrg    if(pSmi->pInt10){
8617104f784Smrg       xf86FreeInt10(pSmi->pInt10);
8627104f784Smrg       pSmi->pInt10 = NULL;
8637104f784Smrg    }
86409885543Smrg
86509885543Smrg    /* Set display resolution */
86609885543Smrg    xf86SetDpi(pScrn, 0, 0);
86709885543Smrg
8687104f784Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
86909885543Smrg	SMI_FreeRec(pScrn);
8707104f784Smrg	LEAVE(FALSE);
87109885543Smrg    }
87209885543Smrg
87309885543Smrg    /* Load XAA or EXA if needed */
87409885543Smrg    if (!pSmi->NoAccel) {
87509885543Smrg	if (!pSmi->useEXA) {
87609885543Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
87709885543Smrg		SMI_FreeRec(pScrn);
8787104f784Smrg		LEAVE(FALSE);
87909885543Smrg	    }
88009885543Smrg	} else {
88109885543Smrg	    XF86ModReqInfo req;
88209885543Smrg	    int errmaj, errmin;
88309885543Smrg
88409885543Smrg	    memset(&req, 0, sizeof(XF86ModReqInfo));
88509885543Smrg	    req.majorversion = 2;
8867104f784Smrg	    req.minorversion = 1;
88709885543Smrg
88809885543Smrg	    if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
88909885543Smrg				&req, &errmaj, &errmin)) {
89009885543Smrg		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
89109885543Smrg		SMI_FreeRec(pScrn);
8927104f784Smrg		LEAVE(FALSE);
89309885543Smrg	    }
89409885543Smrg	}
89509885543Smrg    }
89609885543Smrg
89709885543Smrg    /* Load ramdac if needed */
8987104f784Smrg    if (pSmi->HwCursor) {
89909885543Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
90009885543Smrg	    SMI_FreeRec(pScrn);
9017104f784Smrg	    LEAVE(FALSE);
90209885543Smrg	}
90309885543Smrg    }
90409885543Smrg
9057104f784Smrg    LEAVE(TRUE);
90609885543Smrg}
90709885543Smrg
90809885543Smrg/*
90909885543Smrg * This is called when VT switching back to the X server.  Its job is to
91009885543Smrg * reinitialise the video mode. We may wish to unmap video/MMIO memory too.
91109885543Smrg */
91209885543Smrg
91309885543Smrgstatic Bool
91409885543SmrgSMI_EnterVT(int scrnIndex, int flags)
91509885543Smrg{
91609885543Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
91709885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
91809885543Smrg
9197104f784Smrg    ENTER();
92009885543Smrg
92109885543Smrg    /* Enable MMIO and map memory */
92209885543Smrg    SMI_MapMem(pScrn);
92309885543Smrg
9247104f784Smrg    pSmi->Save(pScrn);
92509885543Smrg
9267104f784Smrg    /* FBBase may have changed after remapping the memory */
9277104f784Smrg    pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
9287104f784Smrg				       -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
9297b58d2e0Smrg#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0))
9307104f784Smrg    pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
9317b58d2e0Smrg#endif
93209885543Smrg
9337104f784Smrg    if(pSmi->useEXA)
9347104f784Smrg       pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
93509885543Smrg
9367104f784Smrg    /* Do the CRTC independent initialization */
9377104f784Smrg    if(!SMI_HWInit(pScrn))
9387104f784Smrg	LEAVE(FALSE);
93909885543Smrg
9407104f784Smrg    /* Initialize the chosen modes */
9417104f784Smrg    if (!xf86SetDesiredModes(pScrn))
9427104f784Smrg	LEAVE(FALSE);
94309885543Smrg
9447104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
9457104f784Smrg		   "Done writing mode.  Register dump:\n");
9467104f784Smrg    SMI_PrintRegs(pScrn);
94709885543Smrg
94809885543Smrg    /* Reset the grapics engine */
94909885543Smrg    if (!pSmi->NoAccel)
95009885543Smrg	SMI_EngineReset(pScrn);
95109885543Smrg
9527104f784Smrg    LEAVE(TRUE);
95309885543Smrg}
95409885543Smrg
95509885543Smrg/*
95609885543Smrg * This is called when VT switching away from the X server.  Its job is to
95709885543Smrg * restore the previous (text) mode. We may wish to remap video/MMIO memory
95809885543Smrg * too.
95909885543Smrg */
96009885543Smrg
96109885543Smrgstatic void
96209885543SmrgSMI_LeaveVT(int scrnIndex, int flags)
96309885543Smrg{
9647104f784Smrg    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
9657104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
96609885543Smrg
9677104f784Smrg    ENTER();
96809885543Smrg
9697104f784Smrg    SMI_AccelSync(pScrn);
97009885543Smrg
9717104f784Smrg    /* Ensure that the rotation BlockHandler is unwrapped, and the shadow
9727104f784Smrg       pixmaps are deallocated, as the video memory is going to be
9737104f784Smrg       unmapped.  */
9747104f784Smrg    xf86RotateCloseScreen(pScrn->pScreen);
97509885543Smrg
9767104f784Smrg    /* Pixmaps that by chance get allocated near the former aperture
9777104f784Smrg       address shouldn't be considered offscreen. */
9787104f784Smrg    if(pSmi->useEXA)
9797104f784Smrg       pSmi->EXADriverPtr->memoryBase=NULL;
98009885543Smrg
9817104f784Smrg    /* Clear frame buffer */
9827104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
9837104f784Smrg
9847104f784Smrg    if (!IS_MSOC(pSmi)) {
9857104f784Smrg	vgaHWPtr	hwp = VGAHWPTR(pScrn);
9867104f784Smrg
9877104f784Smrg	SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
98809885543Smrg    }
9897104f784Smrg    else
9907104f784Smrg	SMI501_WriteMode(pScrn, pSmi->save);
99109885543Smrg
99209885543Smrg    SMI_UnmapMem(pScrn);
99309885543Smrg
9947104f784Smrg    LEAVE();
99509885543Smrg}
99609885543Smrg
99709885543Smrgstatic void
9987104f784SmrgSMI_DetectPanelSize(ScrnInfoPtr pScrn)
99909885543Smrg{
10007104f784Smrg    char	*s;
10017104f784Smrg    int		 width, height;
10027104f784Smrg    SMIPtr	 pSmi = SMIPTR(pScrn);
100309885543Smrg
10047104f784Smrg    pSmi->lcdWidth  = 0;
10057104f784Smrg    pSmi->lcdHeight = 0;
10067104f784Smrg    if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) {
10077104f784Smrg	if (sscanf(s, "%dx%d", &width, &height) != 2)
10087104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
10097104f784Smrg		       "Invalid PanelSize option: %s\n", s);
10107104f784Smrg	else {
10117104f784Smrg	    pSmi->lcdWidth  = width;
10127104f784Smrg	    pSmi->lcdHeight = height;
101309885543Smrg	}
101409885543Smrg    }
101509885543Smrg
10167104f784Smrg    if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) {
10177104f784Smrg	/* panel size detection ... requires BIOS call on 730 hardware */
1018eb3dced6Smacallan#ifdef USE_INT10
10197104f784Smrg	if (pSmi->Chipset == SMI_COUGAR3DR) {
10207104f784Smrg	    if (pSmi->pInt10 != NULL) {
10217104f784Smrg		pSmi->pInt10->num = 0x10;
10227104f784Smrg		pSmi->pInt10->ax  = 0x5F00;
10237104f784Smrg		pSmi->pInt10->bx  = 0;
10247104f784Smrg		pSmi->pInt10->cx  = 0;
10257104f784Smrg		pSmi->pInt10->dx  = 0;
10267104f784Smrg		xf86ExecX86int10(pSmi->pInt10);
10277104f784Smrg		if (pSmi->pInt10->ax == 0x005F) {
10287104f784Smrg		    switch (pSmi->pInt10->cx & 0x0F) {
10297104f784Smrg			case PANEL_640x480:
10307104f784Smrg			    pSmi->lcdWidth  = 640;
10317104f784Smrg			    pSmi->lcdHeight = 480;
10327104f784Smrg			    break;
10337104f784Smrg			case PANEL_800x600:
10347104f784Smrg			    pSmi->lcdWidth  = 800;
10357104f784Smrg			    pSmi->lcdHeight = 600;
10367104f784Smrg			    break;
10377104f784Smrg			case PANEL_1024x768:
10387104f784Smrg			    pSmi->lcdWidth  = 1024;
10397104f784Smrg			    pSmi->lcdHeight = 768;
10407104f784Smrg			    break;
10417104f784Smrg			case PANEL_1280x1024:
10427104f784Smrg			    pSmi->lcdWidth  = 1280;
10437104f784Smrg			    pSmi->lcdHeight = 1024;
10447104f784Smrg			    break;
10457104f784Smrg			case PANEL_1600x1200:
10467104f784Smrg			    pSmi->lcdWidth  = 1600;
10477104f784Smrg			    pSmi->lcdHeight = 1200;
10487104f784Smrg			    break;
10497104f784Smrg			case PANEL_1400x1050:
10507104f784Smrg			    pSmi->lcdWidth  = 1400;
10517104f784Smrg			    pSmi->lcdHeight = 1050;
10527104f784Smrg			    break;
10537104f784Smrg		    }
105409885543Smrg
10557104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10567104f784Smrg			       "Detected panel size via BIOS: %d x %d\n",
10577104f784Smrg			       pSmi->lcdWidth, pSmi->lcdHeight);
105809885543Smrg		}
10597104f784Smrg		else
10607104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10617104f784Smrg			       "BIOS error during 730 panel detection!\n");
106209885543Smrg	    }
10637104f784Smrg	    else  {
10647104f784Smrg		/* int10 support isn't setup on the second call to this function,
10657104f784Smrg		  o if this is the second call, don't do detection again */
10667104f784Smrg		if (pSmi->lcd == 0)
10677104f784Smrg		    /* If we get here, int10 support is not loaded or not working */
10687104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10697104f784Smrg			       "No BIOS support for 730 panel detection!\n");
107009885543Smrg	    }
107109885543Smrg
10727104f784Smrg	    /* Set this to indicate that we've done the detection */
10737104f784Smrg	    pSmi->lcd = 1;
107409885543Smrg	}
1075eb3dced6Smacallan	else
1076eb3dced6Smacallan#endif /* USE_INT10 */
1077eb3dced6Smacallan	if (IS_MSOC(pSmi)) {
10787104f784Smrg	    pSmi->lcdWidth  = (READ_SCR(pSmi, PANEL_WWIDTH)  >> 16) & 2047;
10797104f784Smrg	    pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047;
108009885543Smrg	}
10817104f784Smrg	else {
10827104f784Smrg	    /* panel size detection for hardware other than 730 */
10837104f784Smrg	    pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10847104f784Smrg				     0x31) & 0x01;
108509885543Smrg
10867104f784Smrg	    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10877104f784Smrg			     0x30) & 0x01) {
10887104f784Smrg		pSmi->lcd <<= 1;
10897104f784Smrg	    }
10907104f784Smrg	    switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10917104f784Smrg				 0x30) & 0x0C) {
10927104f784Smrg		case 0x00:
109309885543Smrg		    pSmi->lcdWidth  = 640;
109409885543Smrg		    pSmi->lcdHeight = 480;
109509885543Smrg		    break;
10967104f784Smrg		case 0x04:
109709885543Smrg		    pSmi->lcdWidth  = 800;
109809885543Smrg		    pSmi->lcdHeight = 600;
109909885543Smrg		    break;
11007104f784Smrg		case 0x08:
11017104f784Smrg		    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
11027104f784Smrg				     0x74) & 0x02) {
11037104f784Smrg			pSmi->lcdWidth  = 1024;
11047104f784Smrg			pSmi->lcdHeight = 600;
11057104f784Smrg		    }
11067104f784Smrg		    else {
11077104f784Smrg			pSmi->lcdWidth  = 1024;
11087104f784Smrg			pSmi->lcdHeight = 768;
11097104f784Smrg		    }
111009885543Smrg		    break;
11117104f784Smrg		case 0x0C:
111209885543Smrg		    pSmi->lcdWidth  = 1280;
111309885543Smrg		    pSmi->lcdHeight = 1024;
111409885543Smrg		    break;
111509885543Smrg	    }
111609885543Smrg	}
111709885543Smrg    }
111809885543Smrg
11197104f784Smrg    if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0)
11207104f784Smrg	pSmi->lcdWidth = 1024;
11217104f784Smrg    if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0)
11227104f784Smrg	pSmi->lcdHeight = 768;
11237104f784Smrg
112409885543Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
112509885543Smrg	       (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
112609885543Smrg	       pSmi->lcdWidth, pSmi->lcdHeight);
112709885543Smrg
112809885543Smrg}
112909885543Smrg
11307104f784Smrgstatic void
11317104f784SmrgSMI_DetectMCLK(ScrnInfoPtr pScrn)
11327104f784Smrg{
11337104f784Smrg    double		real;
11347104f784Smrg    MSOCClockRec	clock;
11357104f784Smrg    int			mclk, mxclk;
11367104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
11377104f784Smrg
11387104f784Smrg    /* MCLK defaults */
11397104f784Smrg    if (pSmi->Chipset == SMI_LYNXEMplus){
11407104f784Smrg	/* The SM712 can be safely clocked up to 157MHz, according to
11417104f784Smrg	   Silicon Motion engineers. */
11427104f784Smrg	pSmi->MCLK = 157000;
11437104f784Smrg
11442ec8c4b4Smrg    } else if (IS_MSOC(pSmi)) {
11452ec8c4b4Smrg       /* Set some sane defaults for the clock settings if we are on a
11462ec8c4b4Smrg          SM502 and it's likely to be uninitialized. */
11472ec8c4b4Smrg
11482ec8c4b4Smrg       if (!xf86IsPrimaryPci(pSmi->PciInfo) &&
11492ec8c4b4Smrg           (READ_SCR(pSmi, DEVICE_ID) & 0xFF) >= 0xC0) {
11502ec8c4b4Smrg          pSmi->MCLK = 112000;
11512ec8c4b4Smrg          pSmi->MXCLK = 144000;
11522ec8c4b4Smrg       }
11532ec8c4b4Smrg
11542ec8c4b4Smrg    } else {
11552ec8c4b4Smrg        pSmi->MCLK = 0;
11562ec8c4b4Smrg        pSmi->MXCLK = 0;
11572ec8c4b4Smrg    }
11587104f784Smrg
11597104f784Smrg    /* MCLK from user settings */
11607104f784Smrg    if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
11617104f784Smrg	if (IS_MSOC(pSmi) || (int)real <= 120) {
11627104f784Smrg	    pSmi->MCLK = (int)(real * 1000.0);
11637104f784Smrg	} else {
11647104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
11657104f784Smrg		       "Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
11667104f784Smrg		       real);
11677104f784Smrg	}
11687104f784Smrg    }
11697104f784Smrg    mclk = pSmi->MCLK;
11707104f784Smrg
11717104f784Smrg    if (IS_MSOC(pSmi)) {
11727104f784Smrg	clock.value = READ_SCR(pSmi, CURRENT_CLOCK);
11737104f784Smrg	if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK,
11747104f784Smrg			      OPTUNITS_MHZ, &real))
11757104f784Smrg	    pSmi->MXCLK = (int)(real * 1000.0);
11767104f784Smrg    }
11777104f784Smrg
11787104f784Smrg    /* Already programmed MCLK */
11797104f784Smrg    if (pSmi->MCLK == 0) {
11807104f784Smrg	if (IS_MSOC(pSmi))
11817104f784Smrg	    mclk = ((clock.f.m_select ? 336 : 288) /
11827104f784Smrg		    ((clock.f.m_divider ? 3 : 1) <<
11837104f784Smrg		     (unsigned)clock.f.m_shift)) * 1000;
11847104f784Smrg	else {
11857104f784Smrg	    unsigned char	shift, m, n;
11867104f784Smrg
11877104f784Smrg	    m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
11887104f784Smrg	    n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
11897104f784Smrg	    switch (n >> 6) {
11907104f784Smrg		case 1:
11917104f784Smrg		    shift = 4;
11927104f784Smrg		    break;
11937104f784Smrg		case 2:
11947104f784Smrg		    shift = 2;
11957104f784Smrg		    break;
11967104f784Smrg		default:
11977104f784Smrg		    shift = 1;
11987104f784Smrg		    break;
11997104f784Smrg	    }
12007104f784Smrg	    n &= 0x3F;
12017104f784Smrg	    mclk = ((1431818 * m) / n / shift + 50) / 100;
12027104f784Smrg	}
12037104f784Smrg    }
12047104f784Smrg
12057104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0);
12067104f784Smrg    if (IS_MSOC(pSmi)) {
12077104f784Smrg	if (pSmi->MXCLK == 0) {
12087104f784Smrg	    mxclk = ((clock.f.m1_select ? 336 : 288) /
12097104f784Smrg		     ((clock.f.m1_divider ? 3 : 1) <<
12107104f784Smrg		      (unsigned)clock.f.m1_shift)) * 1000;
12117104f784Smrg	}
12127104f784Smrg	else
12137104f784Smrg	    mxclk = pSmi->MXCLK;
12147104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0);
12157104f784Smrg    }
12167104f784Smrg}
12177104f784Smrg
121809885543Smrgstatic Bool
12197104f784SmrgSMI_MapMmio(ScrnInfoPtr pScrn)
122009885543Smrg{
12217104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
12227104f784Smrg    CARD32	memBase;
122309885543Smrg
12247104f784Smrg    SMI_EnableMmio(pScrn);
122509885543Smrg
122609885543Smrg    switch (pSmi->Chipset) {
12277104f784Smrg	case SMI_COUGAR3DR:
12287104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
12297104f784Smrg	    pSmi->MapSize = 0x200000;
12307104f784Smrg	    break;
12317104f784Smrg	case SMI_LYNX3D:
12327104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000;
12337104f784Smrg	    pSmi->MapSize = 0x180000;
12347104f784Smrg	    break;
12357104f784Smrg	case SMI_LYNXEM:
12367104f784Smrg	case SMI_LYNXEMplus:
12377104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
12387104f784Smrg	    pSmi->MapSize = 0x400000;
12397104f784Smrg	    break;
12407104f784Smrg	case SMI_LYNX3DM:
12417104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
12427104f784Smrg	    pSmi->MapSize = 0x200000;
12437104f784Smrg	    break;
12447104f784Smrg	case SMI_MSOC:
12457104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
12467104f784Smrg	    pSmi->MapSize = 0x200000;
12477104f784Smrg	    break;
12487104f784Smrg	default:
12497104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
12507104f784Smrg	    pSmi->MapSize = 0x10000;
12517104f784Smrg	    break;
125209885543Smrg    }
12537104f784Smrg
12547104f784Smrg#ifndef XSERVER_LIBPCIACCESS
125509885543Smrg    pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
125609885543Smrg				  memBase, pSmi->MapSize);
12577104f784Smrg#else
12587104f784Smrg    {
12597104f784Smrg	void	**result = (void**)&pSmi->MapBase;
12607104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
12617104f784Smrg					     memBase,
12627104f784Smrg					     pSmi->MapSize,
12637104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE,
12647104f784Smrg					     result);
12657104f784Smrg
12667104f784Smrg	if (err)
1267eb3dced6Smacallan	    pSmi->MapBase = NULL;
12687104f784Smrg    }
12697104f784Smrg#endif
127009885543Smrg
127109885543Smrg    if (pSmi->MapBase == NULL) {
127209885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
127309885543Smrg		   "MMIO registers.\n");
12747104f784Smrg	return (FALSE);
127509885543Smrg    }
127609885543Smrg
127709885543Smrg    switch (pSmi->Chipset) {
12787104f784Smrg	case SMI_COUGAR3DR:
12797104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
12807104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
12817104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
12827104f784Smrg	    pSmi->FPRBase = pSmi->MapBase + 0x005800;
12837104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
12847104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
12857104f784Smrg	    pSmi->DataPortSize = 0x100000;
12867104f784Smrg	    break;
12877104f784Smrg	case SMI_LYNX3D:
12887104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
12897104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
12907104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
12917104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x040000;
12927104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x080000;
12937104f784Smrg	    pSmi->DataPortSize = 0x100000;
12947104f784Smrg	    break;
12957104f784Smrg	case SMI_LYNXEM:
12967104f784Smrg	case SMI_LYNXEMplus:
12977104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x008000;
12987104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x00C000;
12997104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x00E000;
13007104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x300000;
13017104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
13027104f784Smrg	    pSmi->DataPortSize = 0x8000 /*0x200000*/;
13037104f784Smrg	    break;
13047104f784Smrg	case SMI_LYNX3DM:
13057104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
13067104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
13077104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
13087104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
13097104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
13107104f784Smrg	    pSmi->DataPortSize = 0x100000;
13117104f784Smrg	    break;
13127104f784Smrg	case SMI_MSOC:
13137104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x100000;
13147104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000000;
13157104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x090000;
13167104f784Smrg	    pSmi->DCRBase = pSmi->MapBase + 0x080000;
13177104f784Smrg	    pSmi->SCRBase = pSmi->MapBase + 0x000000;
13187104f784Smrg	    pSmi->IOBase = 0;
13197104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x110000;
13207104f784Smrg	    pSmi->DataPortSize = 0x10000;
13217104f784Smrg	    break;
13227104f784Smrg	default:
13237104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x8000;
13247104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0xC000;
13257104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0xE000;
13267104f784Smrg	    pSmi->IOBase  = NULL;
13277104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase;
13287104f784Smrg	    pSmi->DataPortSize = 0x8000;
13297104f784Smrg	    break;
133009885543Smrg    }
13317104f784Smrg
133209885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133309885543Smrg		   "Physical MMIO at 0x%08lX\n", (unsigned long)memBase);
133409885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133509885543Smrg		   "Logical MMIO at %p - %p\n", pSmi->MapBase,
133609885543Smrg		   pSmi->MapBase + pSmi->MapSize - 1);
133709885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133809885543Smrg		   "DPR=%p, VPR=%p, IOBase=%p\n",
133909885543Smrg		   pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase);
134009885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
134109885543Smrg		   "DataPort=%p - %p\n", pSmi->DataPortBase,
134209885543Smrg		   pSmi->DataPortBase + pSmi->DataPortSize - 1);
134309885543Smrg
13447104f784Smrg    return (TRUE);
13457104f784Smrg}
134609885543Smrg
13472ec8c4b4Smrg/* HACK - In some cases the BIOS hasn't filled in the "scratchpad
13482ec8c4b4Smrg   registers" (SR71) with the right amount of memory installed (e.g. MIPS
13492ec8c4b4Smrg   platform). Probe it manually. */
13502ec8c4b4Smrgstatic unsigned long
13512ec8c4b4SmrgSMI_ProbeMem(ScrnInfoPtr pScrn, unsigned long mem_skip, unsigned long mem_max)
13522ec8c4b4Smrg{
13532ec8c4b4Smrg    SMIPtr pSmi = SMIPTR(pScrn);
13542ec8c4b4Smrg    unsigned long mem_probe = 1024*1024;
13552ec8c4b4Smrg    unsigned long aperture_base;
13562ec8c4b4Smrg    void* mem;
13572ec8c4b4Smrg
13582ec8c4b4Smrg    ENTER();
13592ec8c4b4Smrg
13602ec8c4b4Smrg    aperture_base = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + mem_skip;
13612ec8c4b4Smrg    mem_max = min(mem_max , PCI_REGION_SIZE(pSmi->PciInfo, 0) - mem_skip);
13622ec8c4b4Smrg
13632ec8c4b4Smrg#ifndef XSERVER_LIBPCIACCESS
13642ec8c4b4Smrg    mem = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
13652ec8c4b4Smrg			aperture_base, mem_max);
13662ec8c4b4Smrg
13672ec8c4b4Smrg    if(!mem)
13682ec8c4b4Smrg	LEAVE(0);
13692ec8c4b4Smrg#else
13702ec8c4b4Smrg    if(pci_device_map_range(pSmi->PciInfo, aperture_base, mem_max,
13712ec8c4b4Smrg			    PCI_DEV_MAP_FLAG_WRITABLE, &mem))
13722ec8c4b4Smrg	LEAVE(0);
13732ec8c4b4Smrg#endif
13742ec8c4b4Smrg
13752ec8c4b4Smrg    while(mem_probe <= mem_max){
13762ec8c4b4Smrg	MMIO_OUT32(mem, mem_probe-4, 0x55555555);
13772ec8c4b4Smrg	if(MMIO_IN32(mem, mem_probe-4) != 0x55555555)
13782ec8c4b4Smrg	    break;
13792ec8c4b4Smrg
13802ec8c4b4Smrg	MMIO_OUT32(mem, mem_probe-4, 0xAAAAAAAA);
13812ec8c4b4Smrg	if(MMIO_IN32(mem, mem_probe-4) != 0xAAAAAAAA)
13822ec8c4b4Smrg	    break;
13832ec8c4b4Smrg
13842ec8c4b4Smrg	mem_probe <<= 1;
13852ec8c4b4Smrg    }
13862ec8c4b4Smrg
13872ec8c4b4Smrg#ifndef XSERVER_LIBPCIACCESS
13882ec8c4b4Smrg    xf86UnMapVidMem(pScrn->scrnIndex, mem, mem_max);
13892ec8c4b4Smrg#else
13902ec8c4b4Smrg    pci_device_unmap_range(pSmi->PciInfo, mem, mem_max);
13912ec8c4b4Smrg#endif
13922ec8c4b4Smrg
13932ec8c4b4Smrg    LEAVE(mem_probe >> 1);
13942ec8c4b4Smrg}
13952ec8c4b4Smrg
13967104f784Smrgstatic Bool
13977104f784SmrgSMI_DetectMem(ScrnInfoPtr pScrn)
13987104f784Smrg{
13997104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
14007104f784Smrg    MessageType from;
140109885543Smrg
14027104f784Smrg    if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){
14037104f784Smrg	pSmi->videoRAMKBytes = pScrn->videoRam;
14047104f784Smrg	from = X_CONFIG;
14057104f784Smrg    }
14067104f784Smrg    else {
14077104f784Smrg	unsigned char	 config;
14087104f784Smrg	static int	 lynx3d_table[4]  = {  0, 2, 4, 6 };
14097104f784Smrg	static int	 lynx3dm_table[4] = { 16, 2, 4, 8 };
14107104f784Smrg	static int	 msoc_table[8]    = {  4, 8, 16, 32, 64, 2, 0, 0 };
14117104f784Smrg	static int	 default_table[4] = {  1, 2, 4, 0 };
14127104f784Smrg
14137104f784Smrg	if (IS_MSOC(pSmi)) {
14147104f784Smrg	    config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7;
14157104f784Smrg	    pSmi->videoRAMKBytes = msoc_table[config] * 1024 -
14167104f784Smrg		SHARED_USB_DMA_BUFFER_SIZE;
14177104f784Smrg	}
14187104f784Smrg	else {
14197104f784Smrg	    config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
14207104f784Smrg	    switch (pSmi->Chipset) {
14217104f784Smrg		case SMI_LYNX3D:
14227104f784Smrg		    pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 +
14237104f784Smrg			512;
14247104f784Smrg		    break;
14252ec8c4b4Smrg		case SMI_LYNXEMplus:
14262ec8c4b4Smrg		    pSmi->videoRAMKBytes = SMI_ProbeMem(pScrn, 0, 0x400000) / 1024;
14272ec8c4b4Smrg		    break;
14287104f784Smrg		case SMI_LYNX3DM:
14297104f784Smrg		    pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024;
14307104f784Smrg		    break;
14317104f784Smrg		case SMI_COUGAR3DR:
14327104f784Smrg		    /* DANGER - Cougar3DR BIOS is broken - hardcode video ram
14337104f784Smrg		     * size per instructions from Silicon Motion engineers */
14347104f784Smrg		    pSmi->videoRAMKBytes = 16 * 1024;
14357104f784Smrg		    break;
14367104f784Smrg		default:
14377104f784Smrg		    pSmi->videoRAMKBytes = default_table[config >> 6] * 1024;
14387104f784Smrg		    break;
14397104f784Smrg	    }
144009885543Smrg	}
14417104f784Smrg	from = X_PROBED;
14427104f784Smrg    }
144309885543Smrg
14447104f784Smrg    pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
14457104f784Smrg    pScrn->videoRam     = pSmi->videoRAMKBytes;
14467104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
14477104f784Smrg	       "videoram: %dkB\n", pSmi->videoRAMKBytes);
144809885543Smrg
14497104f784Smrg    return (TRUE);
14507104f784Smrg}
145109885543Smrg
14527104f784SmrgBool
14537104f784SmrgSMI_MapMem(ScrnInfoPtr pScrn)
14547104f784Smrg{
14557104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
14567104f784Smrg    vgaHWPtr hwp;
145709885543Smrg
14587104f784Smrg    ENTER();
14597104f784Smrg
14607104f784Smrg    if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE)
14617104f784Smrg	LEAVE(FALSE);
14627104f784Smrg
14637104f784Smrg    pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
14647104f784Smrg
14657104f784Smrg    if (pSmi->Chipset == SMI_LYNX3DM)
14667104f784Smrg	pSmi->fbMapOffset = 0x200000;
14677104f784Smrg    else
14687104f784Smrg	pSmi->fbMapOffset = 0x0;
14697104f784Smrg
14707104f784Smrg#ifndef XSERVER_LIBPCIACCESS
14717104f784Smrg    pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex,
14727104f784Smrg				 VIDMEM_FRAMEBUFFER,
14737104f784Smrg				 pSmi->PciTag,
14747104f784Smrg				 pScrn->memPhysBase + pSmi->fbMapOffset,
14757104f784Smrg				 pSmi->videoRAMBytes);
14767104f784Smrg#else
14777104f784Smrg    {
14787104f784Smrg	void	**result = (void**)&pSmi->FBBase;
14797104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
14807104f784Smrg					     pScrn->memPhysBase +
14817104f784Smrg					     pSmi->fbMapOffset,
14827104f784Smrg					     pSmi->videoRAMBytes,
14837104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE |
14847104f784Smrg					     PCI_DEV_MAP_FLAG_WRITE_COMBINE,
14857104f784Smrg					     result);
14867104f784Smrg
14877104f784Smrg	if (err)
14887104f784Smrg	    LEAVE(FALSE);
14897104f784Smrg    }
14907104f784Smrg#endif
14917104f784Smrg
14927104f784Smrg    if (pSmi->FBBase == NULL) {
14937104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
14947104f784Smrg		   "Internal error: could not map framebuffer.\n");
14957104f784Smrg	LEAVE(FALSE);
14967104f784Smrg    }
14977104f784Smrg
14987104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
14997104f784Smrg		   "Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
15007b58d2e0Smrg		   pScrn->memPhysBase, (unsigned long)pSmi->fbMapOffset);
15017104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
15027104f784Smrg		   "Logical frame buffer at %p - %p\n", pSmi->FBBase,
15037104f784Smrg		   pSmi->FBBase + pSmi->videoRAMBytes - 1);
15047104f784Smrg
15057104f784Smrg    if (IS_MSOC(pSmi)) {
15067104f784Smrg	/* Reserve space for panel cursr, and crt if in dual head mode */
15077104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
15087104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15097104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE);
15107104f784Smrg#else
15117104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15127104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE);
15137104f784Smrg
15147104f784Smrg# if SMI501_CLI_DEBUG
15157104f784Smrg	if (pSmi->useEXA) {
15167104f784Smrg	    pSmi->batch_active = FALSE;
15177104f784Smrg	    pSmi->batch_length = 4096;
15187104f784Smrg	    pSmi->FBReserved -= pSmi->batch_length << 3;
15197104f784Smrg	    pSmi->batch_offset = pSmi->FBReserved;
15207104f784Smrg	    pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset);
15217104f784Smrg	    pSmi->batch_finish = -1;
15227104f784Smrg	    pSmi->batch_index = 0;
15237104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
15247104f784Smrg		       "Using command list interpreter debug code\n");
15257104f784Smrg	}
15267104f784Smrg# endif
15277104f784Smrg
15287104f784Smrg#endif
15297104f784Smrg    }
15307104f784Smrg    else {
15317104f784Smrg	/* Set up offset to hwcursor memory area, at the end of
15327104f784Smrg	 * the frame buffer.
15337104f784Smrg	 */
15347104f784Smrg	pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE;
153509885543Smrg	/* set up the fifo reserved space */
153609885543Smrg	if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ {
153709885543Smrg	    CARD32 fifoOffset = 0;
15387104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15397104f784Smrg				       0x46) << 3;
15407104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15417104f784Smrg				       0x47) << 11;
15427104f784Smrg	    fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15437104f784Smrg					0x49) & 0x1C) << 17;
154409885543Smrg	    pSmi->FBReserved = fifoOffset;	/* PDR#1074 */
154509885543Smrg	}
15467104f784Smrg	else
15477104f784Smrg	    pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
154809885543Smrg
15497104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n",
15507104f784Smrg		   (unsigned long)pSmi->FBCursorOffset);
155109885543Smrg
15527104f784Smrg	/* Assign hwp->MemBase & IOBase here */
15537104f784Smrg	hwp = VGAHWPTR(pScrn);
15547104f784Smrg	if (pSmi->IOBase != NULL)
15557104f784Smrg	    vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
15567104f784Smrg	vgaHWGetIOBase(hwp);
155709885543Smrg
15587104f784Smrg	/* Map the VGA memory when the primary video */
15597104f784Smrg	if (xf86IsPrimaryPci(pSmi->PciInfo)) {
15607104f784Smrg	    hwp->MapSize = 0x10000;
15617104f784Smrg	    if (!vgaHWMapMem(pScrn))
15627104f784Smrg		LEAVE(FALSE);
15637104f784Smrg	    pSmi->PrimaryVidMapped = TRUE;
156409885543Smrg	}
156509885543Smrg    }
156609885543Smrg
15677104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n",
15687104f784Smrg	       (unsigned long)pSmi->FBReserved);
15697104f784Smrg
15707104f784Smrg    LEAVE(TRUE);
157109885543Smrg}
157209885543Smrg
157309885543Smrg/* UnMapMem - contains half of pre-4.0 EnterLeave function.  The EnterLeave
157409885543Smrg * function which en/disable access to IO ports and ext. regs
157509885543Smrg */
157609885543Smrg
15777104f784Smrgvoid
157809885543SmrgSMI_UnmapMem(ScrnInfoPtr pScrn)
157909885543Smrg{
158009885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
158109885543Smrg
15827104f784Smrg    ENTER();
158309885543Smrg
158409885543Smrg    /* Unmap VGA mem if mapped. */
158509885543Smrg    if (pSmi->PrimaryVidMapped) {
158609885543Smrg	vgaHWUnmapMem(pScrn);
158709885543Smrg	pSmi->PrimaryVidMapped = FALSE;
158809885543Smrg    }
158909885543Smrg
159009885543Smrg    SMI_DisableMmio(pScrn);
159109885543Smrg
15927104f784Smrg    if (pSmi->MapBase) {
15937104f784Smrg#ifndef XSERVER_LIBPCIACCESS
15947104f784Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase,
15957104f784Smrg			pSmi->MapSize);
15967104f784Smrg#else
15977104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase,
15987104f784Smrg			       pSmi->MapSize);
15997104f784Smrg#endif
16007104f784Smrg	pSmi->MapBase = NULL;
16017104f784Smrg    }
16027104f784Smrg
16037104f784Smrg    if (pSmi->FBBase) {
16047104f784Smrg#ifndef XSERVER_LIBPCIACCESS
160509885543Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
160609885543Smrg			pSmi->videoRAMBytes);
16077104f784Smrg#else
16087104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase,
16097104f784Smrg			       pSmi->videoRAMBytes);
16107104f784Smrg#endif
16117104f784Smrg	pSmi->FBBase = NULL;
161209885543Smrg    }
161309885543Smrg
16147104f784Smrg    LEAVE();
161509885543Smrg}
161609885543Smrg
161709885543Smrg/* This gets called at the start of each server generation. */
161809885543Smrg
161909885543Smrgstatic Bool
162009885543SmrgSMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
162109885543Smrg{
16227104f784Smrg    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
16237104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
16247104f784Smrg    EntityInfoPtr	pEnt;
162509885543Smrg
16267104f784Smrg    ENTER();
162709885543Smrg
162809885543Smrg    /* Map MMIO regs and framebuffer */
16297104f784Smrg    if (!SMI_MapMem(pScrn))
16307104f784Smrg	LEAVE(FALSE);
163109885543Smrg
163209885543Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
163309885543Smrg
16347104f784Smrg    if (!pSmi->pInt10 && pSmi->useBIOS) {
16357104f784Smrg	pSmi->pInt10 = xf86InitInt10(pEnt->index);
163609885543Smrg    }
16377104f784Smrg    if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
16387104f784Smrg	pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
163909885543Smrg    }
164009885543Smrg
16417104f784Smrg    /* Save the chip/graphics state */
16427104f784Smrg    pSmi->Save(pScrn);
164309885543Smrg
16447104f784Smrg    /* Fill in some needed pScrn fields */
16457104f784Smrg    pScrn->vtSema = TRUE;
16467104f784Smrg    pScrn->pScreen = pScreen;
164709885543Smrg
16487104f784Smrg    pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
164909885543Smrg
16507104f784Smrg    pSmi->fbArea = NULL;
16517104f784Smrg    pSmi->FBOffset = 0;
16527104f784Smrg    pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
165309885543Smrg
16547104f784Smrg    /* Clear frame buffer */
16557104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
165609885543Smrg
165709885543Smrg    /*
16587104f784Smrg     * The next step is to setup the screen's visuals, and initialise the
16597104f784Smrg     * framebuffer code.  In cases where the framebuffer's default choises for
16607104f784Smrg     * things like visual layouts and bits per RGB are OK, this may be as simple
16617104f784Smrg     * as calling the framebuffer's ScreenInit() function.  If not, the visuals
16627104f784Smrg     * will need to be setup before calling a fb ScreenInit() function and fixed
16637104f784Smrg     * up after.
16647104f784Smrg     */
166509885543Smrg
16667104f784Smrg    /*
16677104f784Smrg     * Reset the visual list.
16687104f784Smrg     */
16697104f784Smrg    miClearVisualTypes();
167009885543Smrg
16717104f784Smrg    /* Setup the visuals we support. */
167209885543Smrg
16737104f784Smrg    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
16747104f784Smrg			  pScrn->rgbBits, pScrn->defaultVisual))
16757104f784Smrg	LEAVE(FALSE);
167609885543Smrg
16777104f784Smrg    if (!miSetPixmapDepths ())
16787104f784Smrg	LEAVE(FALSE);
167909885543Smrg
16807104f784Smrg    /*
16817104f784Smrg     * Call the framebuffer layer's ScreenInit function
16827104f784Smrg     */
168309885543Smrg
16847104f784Smrg    DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
16857104f784Smrg	  pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
16867104f784Smrg    if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
16877104f784Smrg		     pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
16887104f784Smrg	LEAVE(FALSE);
168909885543Smrg
16907104f784Smrg    xf86SetBlackWhitePixels(pScreen);
169109885543Smrg
16927104f784Smrg    if (pScrn->bitsPerPixel > 8) {
16937104f784Smrg	VisualPtr visual;
16947104f784Smrg	/* Fixup RGB ordering */
16957104f784Smrg	visual = pScreen->visuals + pScreen->numVisuals;
16967104f784Smrg	while (--visual >= pScreen->visuals) {
16977104f784Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
16987104f784Smrg		visual->offsetRed   = pScrn->offset.red;
16997104f784Smrg		visual->offsetGreen = pScrn->offset.green;
17007104f784Smrg		visual->offsetBlue  = pScrn->offset.blue;
17017104f784Smrg		visual->redMask     = pScrn->mask.red;
17027104f784Smrg		visual->greenMask   = pScrn->mask.green;
17037104f784Smrg		visual->blueMask    = pScrn->mask.blue;
17047104f784Smrg	    }
170509885543Smrg	}
170609885543Smrg    }
170709885543Smrg
17087104f784Smrg    /* must be after RGB ordering fixed */
17097104f784Smrg    fbPictureInit(pScreen, 0, 0);
17107104f784Smrg
17117104f784Smrg    /* Do the CRTC independent initialization */
17127104f784Smrg    if(!SMI_HWInit(pScrn))
17137104f784Smrg	LEAVE(FALSE);
171409885543Smrg
17157104f784Smrg    /* Unless using EXA, regardless or using XAA or not, needs offscreen
17167104f784Smrg     * management at least for video. */
17177104f784Smrg    if (pSmi->NoAccel || !pSmi->useEXA) {
17187104f784Smrg	int		numLines;
17197104f784Smrg	BoxRec		AvailFBArea;
172009885543Smrg
17217104f784Smrg	numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
17227104f784Smrg	AvailFBArea.x1 = 0;
17237104f784Smrg	AvailFBArea.y1 = 0;
17247104f784Smrg	AvailFBArea.x2 = pScrn->virtualX;
17257104f784Smrg	AvailFBArea.y2 = numLines;
172609885543Smrg
17277104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
17287104f784Smrg		   "FrameBuffer Box: %d,%d - %d,%d\n",
17297104f784Smrg		   AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
17307104f784Smrg		   AvailFBArea.y2);
173109885543Smrg
17327104f784Smrg	xf86InitFBManager(pScreen, &AvailFBArea);
173309885543Smrg    }
173409885543Smrg
17357104f784Smrg    /* Initialize acceleration layer */
17367104f784Smrg    if (!pSmi->NoAccel) {
17377104f784Smrg	if (pSmi->useEXA && !SMI_EXAInit(pScreen))
17387104f784Smrg	    LEAVE(FALSE);
17397104f784Smrg	else if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
17407104f784Smrg	    LEAVE(FALSE);
174109885543Smrg    }
174209885543Smrg
17437104f784Smrg    /* Initialize the chosen modes */
17447104f784Smrg    if (!xf86SetDesiredModes(pScrn))
17457104f784Smrg	    LEAVE(FALSE);
174609885543Smrg
17477104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
17487104f784Smrg		   "Done writing mode.  Register dump:\n");
17497104f784Smrg    SMI_PrintRegs(pScrn);
175009885543Smrg
17517104f784Smrg    miInitializeBackingStore(pScreen);
175209885543Smrg
17537104f784Smrg#ifdef HAVE_XMODES
17547104f784Smrg    xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
17557104f784Smrg#endif
175609885543Smrg
17577104f784Smrg    /* Initialise cursor functions */
17587104f784Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
175909885543Smrg
17607104f784Smrg    /* Initialize HW cursor layer.  Must follow software cursor
17617104f784Smrg     * initialization.
17627104f784Smrg     */
17637104f784Smrg    if (pSmi->HwCursor) {
17647104f784Smrg	int	size, flags;
17657104f784Smrg
17667104f784Smrg	if (IS_MSOC(pSmi)) {
17677104f784Smrg	    size = SMI501_MAX_CURSOR;
17687104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
17697104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
17707104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
17717104f784Smrg	    if (!pSmi->Dualhead)
17727104f784Smrg		flags |= HARDWARE_CURSOR_ARGB;
17737104f784Smrg#endif
17747104f784Smrg	}
17757104f784Smrg	else {
17767104f784Smrg	    size = SMILYNX_MAX_CURSOR;
17777104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
17787104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
17797104f784Smrg		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
17807104f784Smrg		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
17817104f784Smrg		     HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
17827104f784Smrg		     HARDWARE_CURSOR_INVERT_MASK);
17837104f784Smrg	}
178409885543Smrg
17857104f784Smrg	if (!xf86_cursors_init(pScreen, size, size, flags))
17867104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
17877104f784Smrg		       "Hardware cursor initialization failed\n");
178809885543Smrg    }
178909885543Smrg
17907104f784Smrg    /* Initialise default colormap */
17917104f784Smrg    if (!miCreateDefColormap(pScreen))
17927104f784Smrg	LEAVE(FALSE);
179309885543Smrg
17947104f784Smrg    /* Initialize colormap layer.  Must follow initialization of the default
17957104f784Smrg     * colormap.  And SetGamma call, else it will load palette with solid white.
17967104f784Smrg     */
17977104f784Smrg    if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
17987104f784Smrg			     CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
17997104f784Smrg	LEAVE(FALSE);
180009885543Smrg
18017104f784Smrg    pScreen->SaveScreen = SMI_SaveScreen;
18027104f784Smrg    pSmi->CloseScreen = pScreen->CloseScreen;
18037104f784Smrg    pScreen->CloseScreen = SMI_CloseScreen;
180409885543Smrg
18057104f784Smrg    if ((IS_MSOC(pSmi) &&
18067104f784Smrg	 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
18077104f784Smrg	(!IS_MSOC(pSmi) &&
18087104f784Smrg	 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
18097104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
181009885543Smrg
18117104f784Smrg    SMI_InitVideo(pScreen);
181209885543Smrg
18137104f784Smrg    if(!xf86CrtcScreenInit(pScreen))
18147104f784Smrg	LEAVE(FALSE);
181509885543Smrg
18167104f784Smrg    /* Report any unused options (only for the first generation) */
18177104f784Smrg    if (serverGeneration == 1) {
18187104f784Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
18197104f784Smrg    }
182009885543Smrg
18217104f784Smrg    LEAVE(TRUE);
182209885543Smrg}
182309885543Smrg
182409885543Smrg/*
182509885543Smrg * This is called at the end of each server generation.  It restores the
182609885543Smrg * original (text) mode.  It should also unmap the video memory, and free any
182709885543Smrg * per-generation data allocated by the driver.  It should finish by unwrapping
182809885543Smrg * and calling the saved CloseScreen function.
182909885543Smrg */
183009885543Smrg
183109885543Smrgstatic Bool
183209885543SmrgSMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
183309885543Smrg{
18347104f784Smrg    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
18357104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
18367104f784Smrg    Bool	ret;
183709885543Smrg
18387104f784Smrg    ENTER();
183909885543Smrg
18407104f784Smrg    if (pSmi->HwCursor)
18417104f784Smrg	xf86_cursors_fini(pScreen);
18427104f784Smrg
18437104f784Smrg    if (pScrn->vtSema)
18447104f784Smrg	/* Restore console mode and unmap framebuffer */
18457104f784Smrg	SMI_LeaveVT(scrnIndex, 0);
184609885543Smrg
184709885543Smrg    if (pSmi->XAAInfoRec != NULL) {
184809885543Smrg	XAADestroyInfoRec(pSmi->XAAInfoRec);
184909885543Smrg    }
185009885543Smrg    if (pSmi->EXADriverPtr) {
185109885543Smrg	exaDriverFini(pScreen);
185209885543Smrg	pSmi->EXADriverPtr = NULL;
185309885543Smrg    }
18547104f784Smrg    if (pSmi->pVbe != NULL) {
18557104f784Smrg	vbeFree(pSmi->pVbe);
18567104f784Smrg	pSmi->pVbe = NULL;
185709885543Smrg    }
185809885543Smrg    if (pSmi->pInt10 != NULL) {
185909885543Smrg	xf86FreeInt10(pSmi->pInt10);
186009885543Smrg	pSmi->pInt10 = NULL;
186109885543Smrg    }
186209885543Smrg    if (pSmi->ptrAdaptor != NULL) {
18637b58d2e0Smrg	free(pSmi->ptrAdaptor);
186409885543Smrg    }
186509885543Smrg    if (pSmi->BlockHandler != NULL) {
186609885543Smrg	pScreen->BlockHandler = pSmi->BlockHandler;
186709885543Smrg    }
186809885543Smrg
186909885543Smrg    pScrn->vtSema = FALSE;
187009885543Smrg    pScreen->CloseScreen = pSmi->CloseScreen;
187109885543Smrg    ret = (*pScreen->CloseScreen)(scrnIndex, pScreen);
187209885543Smrg
18737104f784Smrg    LEAVE(ret);
187409885543Smrg}
187509885543Smrg
187609885543Smrgstatic void
187709885543SmrgSMI_FreeScreen(int scrnIndex, int flags)
187809885543Smrg{
187909885543Smrg    SMI_FreeRec(xf86Screens[scrnIndex]);
188009885543Smrg}
188109885543Smrg
188209885543Smrgstatic Bool
188309885543SmrgSMI_SaveScreen(ScreenPtr pScreen, int mode)
188409885543Smrg{
18857104f784Smrg    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
188609885543Smrg
18877104f784Smrg    ENTER();
188809885543Smrg
18897104f784Smrg    if(xf86IsUnblank(mode)){
18907104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
18917104f784Smrg    }else{
18927104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
18937104f784Smrg    }
189409885543Smrg
18957104f784Smrg    LEAVE(TRUE);
189609885543Smrg}
189709885543Smrg
189809885543Smrgvoid
189909885543SmrgSMI_AdjustFrame(int scrnIndex, int x, int y, int flags)
190009885543Smrg{
19017104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(xf86Screens[scrnIndex]);
19027104f784Smrg    xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
190309885543Smrg
19047104f784Smrg    ENTER();
190509885543Smrg
19067104f784Smrg    SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
190709885543Smrg
19087104f784Smrg    LEAVE();
190909885543Smrg}
191009885543Smrg
191109885543SmrgBool
191209885543SmrgSMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
191309885543Smrg{
191409885543Smrg    Bool ret;
19157104f784Smrg    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
19167104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
19177104f784Smrg
19187104f784Smrg    ENTER();
191909885543Smrg
19207104f784Smrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
192109885543Smrg
19227104f784Smrg    if (!pSmi->NoAccel)
19237104f784Smrg	SMI_EngineReset(pScrn);
192409885543Smrg
19257104f784Smrg    LEAVE(ret);
192609885543Smrg}
192709885543Smrg
192809885543Smrgvoid
19297104f784SmrgSMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
19307104f784Smrg		LOCO *colors, VisualPtr pVisual)
193109885543Smrg{
19327104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
19337104f784Smrg    int crtc_idx,i,j;
19347104f784Smrg
19357104f784Smrg    ENTER();
19367104f784Smrg
19377104f784Smrg    if(pScrn->bitsPerPixel == 16){
19387104f784Smrg	/* Expand the RGB 565 palette into the 256-elements LUT */
193909885543Smrg
19407104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19417104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
194209885543Smrg
19437104f784Smrg	    for(i=0; i<numColors; i++){
19447104f784Smrg		int idx = indicies[i];
194509885543Smrg
19467104f784Smrg		if(idx<32){
19477104f784Smrg		    for(j=0; j<8; j++){
19487104f784Smrg			crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
19497104f784Smrg			crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
19507104f784Smrg		    }
19517104f784Smrg		}
19527104f784Smrg
19537104f784Smrg		for(j=0; j<4; j++)
19547104f784Smrg		    crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
19557104f784Smrg	    }
19567104f784Smrg
19577104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
195809885543Smrg    }
19597104f784Smrg    }else{
19607104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19617104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
196209885543Smrg
196309885543Smrg    for(i = 0; i < numColors; i++) {
19647104f784Smrg		int idx = indicies[i];
19657104f784Smrg
19667104f784Smrg		crtcPriv->lut_r[idx] = colors[idx].red << 8;
19677104f784Smrg		crtcPriv->lut_g[idx] = colors[idx].green << 8;
19687104f784Smrg		crtcPriv->lut_b[idx] = colors[idx].blue << 8;
19697104f784Smrg	    }
19707104f784Smrg
19717104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
19727104f784Smrg	}
197309885543Smrg    }
197409885543Smrg
19757104f784Smrg    LEAVE();
197609885543Smrg}
197709885543Smrg
197809885543Smrgstatic void
197909885543SmrgSMI_DisableVideo(ScrnInfoPtr pScrn)
198009885543Smrg{
198109885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
198209885543Smrg    CARD8 tmp;
198309885543Smrg
19847104f784Smrg    if (!IS_MSOC(pSmi)) {
19857104f784Smrg	if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
19867104f784Smrg	    return;
19877104f784Smrg	pSmi->DACmask = tmp;
19887104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, 0);
19897104f784Smrg    }
199009885543Smrg}
199109885543Smrg
199209885543Smrgstatic void
199309885543SmrgSMI_EnableVideo(ScrnInfoPtr pScrn)
199409885543Smrg{
199509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
199609885543Smrg
19977104f784Smrg    if (!IS_MSOC(pSmi)) {
19987104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
19997104f784Smrg    }
200009885543Smrg}
200109885543Smrg
200209885543Smrg
200309885543Smrgvoid
200409885543SmrgSMI_EnableMmio(ScrnInfoPtr pScrn)
200509885543Smrg{
200609885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
200709885543Smrg
20087104f784Smrg    ENTER();
200909885543Smrg
20107104f784Smrg    if (!IS_MSOC(pSmi)) {
20117104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
20127104f784Smrg	CARD8 tmp;
20137104f784Smrg
20147104f784Smrg	/*
20157104f784Smrg	 * Enable chipset (seen on uninitialized secondary cards) might not be
20167104f784Smrg	 * needed once we use the VGA softbooter
20177104f784Smrg	 */
20187104f784Smrg	vgaHWSetStdFuncs(hwp);
201909885543Smrg
20207104f784Smrg	/* Enable linear mode */
20217104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20227104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20237104f784Smrg	pSmi->SR18Value = tmp;					/* PDR#521 */
20247104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11);
202509885543Smrg
20267104f784Smrg	/* Enable 2D/3D Engine and Video Processor */
20277104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20287104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20297104f784Smrg	pSmi->SR21Value = tmp;					/* PDR#521 */
20307104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03);
20317104f784Smrg    }
203209885543Smrg
20337104f784Smrg    LEAVE();
203409885543Smrg}
203509885543Smrg
203609885543Smrgvoid
203709885543SmrgSMI_DisableMmio(ScrnInfoPtr pScrn)
203809885543Smrg{
203909885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
204009885543Smrg
20417104f784Smrg    ENTER();
204209885543Smrg
20437104f784Smrg    if (!IS_MSOC(pSmi)) {
20447104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
204509885543Smrg
20467104f784Smrg	vgaHWSetStdFuncs(hwp);
204709885543Smrg
20487104f784Smrg	/* Disable 2D/3D Engine and Video Processor */
20497104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20507104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value);	/* PDR#521 */
20517104f784Smrg
20527104f784Smrg	/* Disable linear mode */
20537104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20547104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value);	/* PDR#521 */
20557104f784Smrg    }
205609885543Smrg
20577104f784Smrg    LEAVE();
205809885543Smrg}
205909885543Smrg
206009885543Smrgstatic void
20617104f784SmrgSMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
20627104f784Smrg{
20637104f784Smrg    vbeInfoPtr pVbe;
20647104f784Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
20657104f784Smrg	pVbe = VBEInit(NULL, index);
20667104f784Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
20677104f784Smrg	vbeFree(pVbe);
20687104f784Smrg    }
20697104f784Smrg}
20707104f784Smrg
20717104f784Smrgstatic Bool
20727104f784SmrgSMI_HWInit(ScrnInfoPtr pScrn)
207309885543Smrg{
207409885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
207509885543Smrg
20767104f784Smrg    ENTER();
207709885543Smrg
20787104f784Smrg    if(IS_MSOC(pSmi))
20797104f784Smrg	LEAVE(SMI501_HWInit(pScrn));
20807104f784Smrg    else
20817104f784Smrg	LEAVE(SMILynx_HWInit(pScrn));
20827104f784Smrg}
208309885543Smrg
20847104f784Smrgvoid
20857104f784SmrgSMI_PrintRegs(ScrnInfoPtr pScrn)
20867104f784Smrg{
20877104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
20887104f784Smrg    int i;
208909885543Smrg
20907104f784Smrg    ENTER();
209109885543Smrg
20927104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
20937104f784Smrg		"START register dump ------------------\n");
20947104f784Smrg
20957104f784Smrg    if(IS_MSOC(pSmi))
20967104f784Smrg	SMI501_PrintRegs(pScrn);
20977104f784Smrg    else
20987104f784Smrg	SMILynx_PrintRegs(pScrn);
209909885543Smrg
210009885543Smrg
210109885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nDPR    x0       x4       x8       xC");
210209885543Smrg    for (i = 0x00; i <= 0x44; i += 4) {
210309885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
210409885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i));
210509885543Smrg    }
210609885543Smrg
210709885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nVPR    x0       x4       x8       xC");
210809885543Smrg    for (i = 0x00; i <= 0x60; i += 4) {
210909885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
211009885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i));
211109885543Smrg    }
211209885543Smrg
211309885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nCPR    x0       x4       x8       xC");
211409885543Smrg    for (i = 0x00; i <= 0x18; i += 4) {
211509885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
211609885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i));
211709885543Smrg    }
211809885543Smrg
211909885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\n");
212009885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
212109885543Smrg		"END register dump --------------------\n");
212209885543Smrg
21237104f784Smrg    LEAVE();
212409885543Smrg}
2125