smi_driver.c revision 5805b606
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
575788ca14Smrg
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);
755788ca14Smrgstatic Bool SMI_EnterVT(VT_FUNC_ARGS_DECL);
765788ca14Smrgstatic void SMI_LeaveVT(VT_FUNC_ARGS_DECL);
775788ca14Smrgstatic Bool SMI_ScreenInit(SCREEN_INIT_ARGS_DECL);
7809885543Smrgstatic void SMI_DisableVideo(ScrnInfoPtr pScrn);
7909885543Smrgstatic void SMI_EnableVideo(ScrnInfoPtr pScrn);
805788ca14Smrgstatic Bool SMI_CloseScreen(CLOSE_SCREEN_ARGS_DECL);
8109885543Smrgstatic Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
825788ca14Smrgstatic void SMI_FreeScreen(FREE_SCREEN_ARGS_DECL);
8309885543Smrgstatic void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
8409885543Smrgstatic void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
857104f784Smrgstatic void SMI_DetectMCLK(ScrnInfoPtr pScrn);
8609885543Smrg
87407d2e45Smacallanstatic Bool SMI_driverFunc(ScrnInfoPtr, xorgDriverFuncOp, pointer);
88407d2e45Smacallan
897104f784Smrg/*
907104f784Smrg * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
917104f784Smrg * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion"
927104f784Smrg */
937104f784Smrg#define SILICONMOTION_NAME          "SMI"
9409885543Smrg#define SILICONMOTION_DRIVER_NAME   "siliconmotion"
957104f784Smrg#define SILICONMOTION_VERSION_NAME  PACKAGE_VERSION
967104f784Smrg#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR
977104f784Smrg#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR
987104f784Smrg#define SILICONMOTION_PATCHLEVEL    PACKAGE_VERSION_PATCHLEVEL
9909885543Smrg#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
10009885543Smrg                                      (SILICONMOTION_VERSION_MINOR << 16) | \
10109885543Smrg                                      (SILICONMOTION_PATCHLEVEL))
10209885543Smrg
1037104f784Smrg#if SMI_DEBUG
1047104f784Smrgint smi_indent = 1;
1057104f784Smrg#endif
1067104f784Smrg
1077104f784Smrg/* for dualhead */
1087104f784Smrgint gSMIEntityIndex = -1;
1097104f784Smrg
11009885543Smrg/*
11109885543Smrg * This contains the functions needed by the server after loading the
11209885543Smrg * driver module.  It must be supplied, and gets added the driver list by
11309885543Smrg * the Module Setup funtion in the dynamic case.  In the static case a
11409885543Smrg * reference to this is compiled in, and this requires that the name of
11509885543Smrg * this DriverRec be an upper-case version of the driver name.
11609885543Smrg */
11709885543Smrg
11809885543Smrg_X_EXPORT DriverRec SILICONMOTION =
11909885543Smrg{
12009885543Smrg    SILICONMOTION_DRIVER_VERSION,
12109885543Smrg    SILICONMOTION_DRIVER_NAME,
12209885543Smrg    SMI_Identify,
12309885543Smrg    SMI_Probe,
12409885543Smrg    SMI_AvailableOptions,
12509885543Smrg    NULL,
126407d2e45Smacallan    0,
127407d2e45Smacallan    SMI_driverFunc
12809885543Smrg};
12909885543Smrg
13009885543Smrg/* Supported chipsets */
13109885543Smrgstatic SymTabRec SMIChipsets[] =
13209885543Smrg{
13309885543Smrg    { PCI_CHIP_SMI910, "Lynx"    },
13409885543Smrg    { PCI_CHIP_SMI810, "LynxE"   },
13509885543Smrg    { PCI_CHIP_SMI820, "Lynx3D"  },
13609885543Smrg    { PCI_CHIP_SMI710, "LynxEM"  },
13709885543Smrg    { PCI_CHIP_SMI712, "LynxEM+" },
13809885543Smrg    { PCI_CHIP_SMI720, "Lynx3DM" },
13909885543Smrg    { PCI_CHIP_SMI731, "Cougar3DR" },
1407104f784Smrg    { PCI_CHIP_SMI501, "MSOC"	 },
14109885543Smrg    { -1,             NULL      }
14209885543Smrg};
14309885543Smrg
14409885543Smrgstatic PciChipsets SMIPciChipsets[] =
14509885543Smrg{
1467104f784Smrg    /* numChipset,	PciID,			Resource */
14709885543Smrg    { PCI_CHIP_SMI910,	PCI_CHIP_SMI910,	RES_SHARED_VGA },
14809885543Smrg    { PCI_CHIP_SMI810,	PCI_CHIP_SMI810,	RES_SHARED_VGA },
14909885543Smrg    { PCI_CHIP_SMI820,	PCI_CHIP_SMI820,	RES_SHARED_VGA },
15009885543Smrg    { PCI_CHIP_SMI710,	PCI_CHIP_SMI710,	RES_SHARED_VGA },
15109885543Smrg    { PCI_CHIP_SMI712,	PCI_CHIP_SMI712,	RES_SHARED_VGA },
15209885543Smrg    { PCI_CHIP_SMI720,	PCI_CHIP_SMI720,	RES_SHARED_VGA },
15309885543Smrg    { PCI_CHIP_SMI731,	PCI_CHIP_SMI731,	RES_SHARED_VGA },
1547104f784Smrg    { PCI_CHIP_SMI501,	PCI_CHIP_SMI501,	RES_UNDEFINED  },
1557104f784Smrg    { -1,		-1,			RES_UNDEFINED  }
15609885543Smrg};
15709885543Smrg
15809885543Smrgtypedef enum
15909885543Smrg{
16009885543Smrg    OPTION_PCI_BURST,
16109885543Smrg    OPTION_PCI_RETRY,
16209885543Smrg    OPTION_NOACCEL,
16309885543Smrg    OPTION_MCLK,
1647104f784Smrg    OPTION_MXCLK,
16509885543Smrg    OPTION_SWCURSOR,
16609885543Smrg    OPTION_HWCURSOR,
16709885543Smrg    OPTION_VIDEOKEY,
16809885543Smrg    OPTION_BYTESWAP,
16909885543Smrg    /* CZ 26.10.2001: interlaced video */
17009885543Smrg    OPTION_INTERLACED,
17109885543Smrg    /* end CZ */
17209885543Smrg    OPTION_USEBIOS,
17309885543Smrg    OPTION_DUALHEAD,
17409885543Smrg    OPTION_ACCELMETHOD,
1757104f784Smrg    OPTION_PANEL_SIZE,
1767104f784Smrg    OPTION_USE_FBDEV,
1777104f784Smrg    OPTION_CSCVIDEO,
17809885543Smrg    NUMBER_OF_OPTIONS
17909885543Smrg} SMIOpts;
18009885543Smrg
18109885543Smrgstatic const OptionInfoRec SMIOptions[] =
18209885543Smrg{
1837104f784Smrg    { OPTION_PCI_BURST,	     "pci_burst",	  OPTV_BOOLEAN, {0}, TRUE },
1847104f784Smrg    { OPTION_PCI_RETRY,	     "pci_retry",	  OPTV_BOOLEAN, {0}, TRUE },
18509885543Smrg    { OPTION_NOACCEL,	     "NoAccel",		  OPTV_BOOLEAN, {0}, FALSE },
1867104f784Smrg    { OPTION_MCLK,	     "MCLK",		  OPTV_FREQ,	{0}, FALSE },
1877104f784Smrg    { OPTION_MXCLK,	     "MXCLK",		  OPTV_FREQ,	{0}, FALSE },
1887104f784Smrg    { OPTION_HWCURSOR,	     "HWCursor",	  OPTV_BOOLEAN, {0}, TRUE },
18909885543Smrg    { OPTION_SWCURSOR,	     "SWCursor",	  OPTV_BOOLEAN, {0}, FALSE },
19009885543Smrg    { OPTION_VIDEOKEY,	     "VideoKey",	  OPTV_INTEGER, {0}, FALSE },
19109885543Smrg    { OPTION_BYTESWAP,	     "ByteSwap",	  OPTV_BOOLEAN, {0}, FALSE },
19209885543Smrg    /* CZ 26.10.2001: interlaced video */
1937104f784Smrg    { OPTION_INTERLACED,     "Interlaced",        OPTV_BOOLEAN, {0}, FALSE },
19409885543Smrg    /* end CZ */
19509885543Smrg    { OPTION_USEBIOS,	     "UseBIOS",		  OPTV_BOOLEAN,	{0}, FALSE },
1967104f784Smrg    { OPTION_DUALHEAD,	     "Dualhead",	  OPTV_BOOLEAN,	{0}, TRUE },
19709885543Smrg    { OPTION_ACCELMETHOD,    "AccelMethod",       OPTV_STRING,  {0}, FALSE },
1987104f784Smrg    { OPTION_PANEL_SIZE,     "PanelSize",	  OPTV_ANYSTR,	{0}, FALSE },
1997104f784Smrg    { OPTION_USE_FBDEV,	     "UseFBDev",	  OPTV_BOOLEAN,	{0}, FALSE },
2007104f784Smrg    { OPTION_CSCVIDEO,	     "CSCVideo",	  OPTV_BOOLEAN, {0}, TRUE },
20109885543Smrg    { -1,		     NULL,		  OPTV_NONE,	{0}, FALSE }
20209885543Smrg};
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;
241407d2e45Smacallan	xf86AddDriver(&SILICONMOTION, module, HaveDriverFuncs);
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
25709885543Smrgstatic Bool
25809885543SmrgSMI_GetRec(ScrnInfoPtr pScrn)
25909885543Smrg{
2607104f784Smrg    ENTER();
26109885543Smrg
26209885543Smrg    /*
26309885543Smrg     * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
26409885543Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
26509885543Smrg     * the allocation has already been done.
26609885543Smrg     */
26709885543Smrg    if (pScrn->driverPrivate == NULL) {
26809885543Smrg	pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
26909885543Smrg    }
27009885543Smrg
2717104f784Smrg    LEAVE(TRUE);
27209885543Smrg}
27309885543Smrg
27409885543Smrgstatic void
27509885543SmrgSMI_FreeRec(ScrnInfoPtr pScrn)
27609885543Smrg{
2777104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
27809885543Smrg
2797104f784Smrg    ENTER();
2807104f784Smrg
2817104f784Smrg    if (pSmi) {
2827b58d2e0Smrg	free(pSmi->save);
2837b58d2e0Smrg	free(pSmi->mode);
2847b58d2e0Smrg	free(pScrn->driverPrivate);
28509885543Smrg	pScrn->driverPrivate = NULL;
28609885543Smrg    }
28709885543Smrg
2887104f784Smrg    LEAVE();
28909885543Smrg}
29009885543Smrg
29109885543Smrgstatic const OptionInfoRec *
29209885543SmrgSMI_AvailableOptions(int chipid, int busid)
29309885543Smrg{
2947104f784Smrg    ENTER();
2957104f784Smrg
2967104f784Smrg    LEAVE(SMIOptions);
29709885543Smrg}
29809885543Smrg
29909885543Smrgstatic void
30009885543SmrgSMI_Identify(int flags)
30109885543Smrg{
3027104f784Smrg    ENTER();
30309885543Smrg
30409885543Smrg    xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
30509885543Smrg		SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
30609885543Smrg		SMIChipsets);
30709885543Smrg
3087104f784Smrg    LEAVE();
30909885543Smrg}
31009885543Smrg
31109885543Smrgstatic Bool
31209885543SmrgSMI_Probe(DriverPtr drv, int flags)
31309885543Smrg{
31409885543Smrg    int i;
31509885543Smrg    GDevPtr *devSections;
31609885543Smrg    int *usedChips;
31709885543Smrg    int numDevSections;
31809885543Smrg    int numUsed;
31909885543Smrg    Bool foundScreen = FALSE;
32009885543Smrg
3217104f784Smrg    ENTER();
32209885543Smrg
32309885543Smrg    numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
32409885543Smrg
3257104f784Smrg    if (numDevSections <= 0)
32609885543Smrg	/* There's no matching device section in the config file, so quit now. */
3277104f784Smrg	LEAVE(FALSE);
32809885543Smrg
3297104f784Smrg#ifndef XSERVER_LIBPCIACCESS
3307104f784Smrg    if (xf86GetPciVideoInfo() == NULL)
3317104f784Smrg	LEAVE(FALSE);
3327104f784Smrg#endif
33309885543Smrg
33409885543Smrg    numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
33509885543Smrg				    SMIChipsets, SMIPciChipsets, devSections,
33609885543Smrg				    numDevSections, drv, &usedChips);
33709885543Smrg
33809885543Smrg    /* Free it since we don't need that list after this */
3397b58d2e0Smrg    free(devSections);
3407104f784Smrg    if (numUsed <= 0)
3417104f784Smrg	LEAVE(FALSE);
3427104f784Smrg
3437104f784Smrg    if (flags & PROBE_DETECT)
3447104f784Smrg	foundScreen = TRUE;
3457104f784Smrg    else {
3467104f784Smrg	ScrnInfoPtr	pScrn;
3477104f784Smrg	EntityInfoPtr	pEnt;
34809885543Smrg
34909885543Smrg	for (i = 0; i < numUsed; i++) {
3507104f784Smrg	    if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
3517104f784Smrg					     SMIPciChipsets, NULL,
3527104f784Smrg					     NULL, NULL, NULL, NULL))) {
3537104f784Smrg		pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
3547104f784Smrg		pScrn->driverName    = SILICONMOTION_DRIVER_NAME;
3557104f784Smrg		pScrn->name	     = SILICONMOTION_NAME;
3567104f784Smrg		pScrn->Probe	     = SMI_Probe;
3577104f784Smrg		pScrn->PreInit	     = SMI_PreInit;
3587104f784Smrg		pScrn->ScreenInit    = SMI_ScreenInit;
3597104f784Smrg		pScrn->SwitchMode    = SMI_SwitchMode;
3607104f784Smrg		pScrn->AdjustFrame   = SMI_AdjustFrame;
3617104f784Smrg
3627104f784Smrg		if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
3637104f784Smrg			pScrn->EnterVT   = SMI_EnterVT;
3647104f784Smrg			pScrn->LeaveVT   = SMI_LeaveVT;
3657b58d2e0Smrg		    free(pEnt);
3667104f784Smrg		}
3677104f784Smrg		pScrn->FreeScreen    = SMI_FreeScreen;
3687104f784Smrg		foundScreen	     = TRUE;
3697104f784Smrg	    }
37009885543Smrg	}
37109885543Smrg    }
3727b58d2e0Smrg    free(usedChips);
37309885543Smrg
3747104f784Smrg    LEAVE(foundScreen);
37509885543Smrg}
37609885543Smrg
37709885543Smrgstatic Bool
37809885543SmrgSMI_PreInit(ScrnInfoPtr pScrn, int flags)
37909885543Smrg{
38009885543Smrg    EntityInfoPtr pEnt;
38109885543Smrg    SMIPtr pSmi;
38209885543Smrg    MessageType from;
38309885543Smrg    vgaHWPtr hwp;
38409885543Smrg
3857104f784Smrg    ENTER();
38609885543Smrg
38709885543Smrg    /* Ignoring the Type list for now.  It might be needed when multiple cards
38809885543Smrg     * are supported.
38909885543Smrg     */
3907104f784Smrg    if (pScrn->numEntities > 1)
3917104f784Smrg	LEAVE(FALSE);
39209885543Smrg
3937104f784Smrg    /* Allocate the SMIRec driverPrivate */
3947104f784Smrg    if (!SMI_GetRec(pScrn))
3957104f784Smrg	LEAVE(FALSE);
3967104f784Smrg    pSmi = SMIPTR(pScrn);
39709885543Smrg
3987104f784Smrg    /* Find the PCI slot for this screen */
3997104f784Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
40009885543Smrg
4017104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
4027104f784Smrg    pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
4037104f784Smrg
4047104f784Smrg    if (IS_MSOC(pSmi)) {
4057104f784Smrg	pSmi->Save = SMI501_Save;
4067104f784Smrg	pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
4077104f784Smrg	pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
4087104f784Smrg    }
4097104f784Smrg    else {
4107104f784Smrg	pSmi->Save = SMILynx_Save;
4117104f784Smrg	pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
4127104f784Smrg	pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
41309885543Smrg    }
41409885543Smrg
4157104f784Smrg    if (flags & PROBE_DETECT) {
4167104f784Smrg	if (!IS_MSOC(pSmi))
4177104f784Smrg	    SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
4187104f784Smrg	LEAVE(TRUE);
41909885543Smrg    }
4207104f784Smrg
421b698ba48Smrg    if (pEnt->location.type != BUS_PCI) {
4227b58d2e0Smrg	free(pEnt);
4237104f784Smrg	SMI_FreeRec(pScrn);
4247104f784Smrg	LEAVE(FALSE);
4257104f784Smrg    }
4267104f784Smrg    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
42709885543Smrg
42809885543Smrg    /* Set pScrn->monitor */
42909885543Smrg    pScrn->monitor = pScrn->confScreen->monitor;
43009885543Smrg
4317104f784Smrg    if (!IS_MSOC(pSmi)) {
4327104f784Smrg	/* The vgahw module should be loaded here when needed */
4337104f784Smrg	if (!xf86LoadSubModule(pScrn, "vgahw"))
4347104f784Smrg	    LEAVE(FALSE);
4357104f784Smrg
4367104f784Smrg	/*
4377104f784Smrg	 * Allocate a vgaHWRec
4387104f784Smrg	 */
4397104f784Smrg	if (!vgaHWGetHWRec(pScrn))
4407104f784Smrg	    LEAVE(FALSE);
4417104f784Smrg
4427104f784Smrg	hwp = VGAHWPTR(pScrn);
4435788ca14Smrg	vgaHWSetStdFuncs(hwp);
4445788ca14Smrg#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
4457104f784Smrg	pSmi->PIOBase = hwp->PIOOffset;
4465788ca14Smrg#else
4475788ca14Smrg	pSmi->PIOBase = 0;
4485788ca14Smrg#endif
4497104f784Smrg
4507104f784Smrg	xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
4517104f784Smrg		       "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET,
4527104f784Smrg		       hwp->IOBase, hwp->MMIOBase);
4537104f784Smrg    }
4547104f784Smrg
45509885543Smrg    /*
45609885543Smrg     * The first thing we should figure out is the depth, bpp, etc.
45709885543Smrg     */
4587104f784Smrg    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
4597104f784Smrg	LEAVE(FALSE);
46009885543Smrg
46109885543Smrg    /* Check that the returned depth is one we support */
4627104f784Smrg    if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) {
46309885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
46409885543Smrg		   "Given depth (%d) is not supported by this driver\n",
46509885543Smrg		   pScrn->depth);
4667104f784Smrg	LEAVE(FALSE);
4677104f784Smrg    }
4687104f784Smrg
4697104f784Smrg
4707104f784Smrg    if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
4717104f784Smrg       pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
4727104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4737104f784Smrg		   "Given bpp (%d) is not supported by this driver\n",
4747104f784Smrg		   pScrn->bitsPerPixel);
4757104f784Smrg	LEAVE(FALSE);
47609885543Smrg    }
47709885543Smrg
47809885543Smrg    xf86PrintDepthBpp(pScrn);
47909885543Smrg
4802ec8c4b4Smrg    pSmi->Bpp = pScrn->bitsPerPixel >> 3;
4812ec8c4b4Smrg
48209885543Smrg    /*
48309885543Smrg     * This must happen after pScrn->display has been set because
48409885543Smrg     * xf86SetWeight references it.
48509885543Smrg     */
48609885543Smrg    if (pScrn->depth > 8) {
48709885543Smrg	/* The defaults are OK for us */
48809885543Smrg	rgb zeros = {0, 0, 0};
4896adb3ac0Smacallan
4907104f784Smrg#if __BYTE_ORDER == __BIG_ENDIAN
4917104f784Smrg	rgb masks = {0xff00,0xff0000,0xff000000};
4927104f784Smrg#else
4937104f784Smrg	rgb masks = {0, 0, 0};
4947104f784Smrg#endif
49509885543Smrg
4967104f784Smrg	if (!xf86SetWeight(pScrn, zeros, masks))
4977104f784Smrg	    LEAVE(FALSE);
49809885543Smrg    }
49909885543Smrg
5007104f784Smrg    if (!xf86SetDefaultVisual(pScrn, -1))
5017104f784Smrg	LEAVE(FALSE);
50209885543Smrg
50309885543Smrg    /* We don't currently support DirectColor at > 8bpp */
5047104f784Smrg    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
50509885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) "
50609885543Smrg		   "is not supported at depth %d\n",
50709885543Smrg		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
5087104f784Smrg	LEAVE(FALSE);
50909885543Smrg    }
51009885543Smrg
51109885543Smrg    /* We use a programmable clock */
51209885543Smrg    pScrn->progClock = TRUE;
51309885543Smrg
51409885543Smrg    /* Collect all of the relevant option flags (fill in pScrn->options) */
51509885543Smrg    xf86CollectOptions(pScrn, NULL);
51609885543Smrg
51709885543Smrg    /* Set the bits per RGB for 8bpp mode */
5187104f784Smrg    if (pScrn->depth == 8){
5197104f784Smrg	pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
5207104f784Smrg    }else if(pScrn->depth == 16){
5217104f784Smrg	/* Use 8 bit LUT for gamma correction*/
5227104f784Smrg	pScrn->rgbBits = 8;
52309885543Smrg    }
52409885543Smrg
52509885543Smrg    /* Process the options */
5267b58d2e0Smrg    if (!(pSmi->Options = malloc(sizeof(SMIOptions))))
5277104f784Smrg	LEAVE(FALSE);
5287104f784Smrg
52909885543Smrg    memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
53009885543Smrg    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
53109885543Smrg
5327104f784Smrg    /* Enable pci burst by default */
5337104f784Smrg    from = X_DEFAULT;
5347104f784Smrg    pSmi->PCIBurst = TRUE;
5357104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst))
5367104f784Smrg	from = X_CONFIG;
5377104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n",
5387104f784Smrg	       pSmi->PCIBurst ? "en" : "dis");
53909885543Smrg
5407104f784Smrg    /* Pci retry enabled by default if pci burst also enabled */
5417104f784Smrg    from = X_DEFAULT;
5427104f784Smrg    pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE;
5437104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) {
5447104f784Smrg	from = X_CONFIG;
5457104f784Smrg	if (pSmi->PCIRetry && !pSmi->PCIBurst) {
5467104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5477104f784Smrg		       "\"pci_retry\" option requires \"pci_burst\".\n");
5487104f784Smrg	    pSmi->PCIRetry = FALSE;
54909885543Smrg	}
55009885543Smrg    }
5517104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n",
5527104f784Smrg	       pSmi->PCIRetry ? "en" : "dis");
55309885543Smrg
55409885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) {
55509885543Smrg	pSmi->NoAccel = TRUE;
55609885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
55709885543Smrg		   "disabled\n");
55809885543Smrg    } else {
55909885543Smrg	pSmi->NoAccel = FALSE;
56009885543Smrg    }
56109885543Smrg
5627104f784Smrg    if (IS_MSOC(pSmi)) {
5637104f784Smrg	from = X_DEFAULT;
5647104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
5657104f784Smrg	    from = X_CONFIG;
5667104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n",
5677104f784Smrg		   pSmi->UseFBDev ? "enabled" : "disabled");
5687104f784Smrg    }
5697104f784Smrg
5707104f784Smrg    from = X_CONFIG;
5717104f784Smrg    pSmi->HwCursor = TRUE;
5727104f784Smrg    /* SWCursor overrides HWCusor if both specified */
5737104f784Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
5747104f784Smrg	pSmi->HwCursor = FALSE;
5757104f784Smrg    else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
5767104f784Smrg	from = X_DEFAULT;
57709885543Smrg
5787104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
5797104f784Smrg	       pSmi->HwCursor ? "Hard" : "Soft");
58009885543Smrg
58109885543Smrg    if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
58209885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
58309885543Smrg		   "0x%08X\n", pSmi->videoKey);
58409885543Smrg    } else {
58509885543Smrg	pSmi->videoKey = (1 << pScrn->offset.red) |
58609885543Smrg			 (1 << pScrn->offset.green) |
58709885543Smrg			 (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
58809885543Smrg			 << pScrn->offset.blue);
58909885543Smrg    }
59009885543Smrg
59109885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) {
59209885543Smrg	pSmi->ByteSwap = TRUE;
59309885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
59409885543Smrg    } else {
59509885543Smrg	pSmi->ByteSwap = FALSE;
59609885543Smrg    }
59709885543Smrg
59809885543Smrg    /* CZ 26.10.2001: interlaced video */
59909885543Smrg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) {
60009885543Smrg	pSmi->interlaced = TRUE;
60109885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
60209885543Smrg    } else {
60309885543Smrg	pSmi->interlaced = FALSE;
60409885543Smrg    }
60509885543Smrg    /* end CZ */
60609885543Smrg
6077104f784Smrg    if (IS_MSOC(pSmi))
6087104f784Smrg	pSmi->useBIOS = FALSE;
6097104f784Smrg    else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) {
61009885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
61109885543Smrg		   pSmi->useBIOS ? "enabled" : "disabled");
6127104f784Smrg    }
6137104f784Smrg    else if(pSmi->Chipset == SMI_LYNX3DM){
6147104f784Smrg	/* Default to UseBIOS disabled. */
6157104f784Smrg	pSmi->useBIOS = FALSE;
6167104f784Smrg    }
6177104f784Smrg    else {
61809885543Smrg	/* Default to UseBIOS enabled. */
61909885543Smrg	pSmi->useBIOS = TRUE;
62009885543Smrg    }
62109885543Smrg
6227104f784Smrg    if (pSmi->useBIOS) {
6237104f784Smrg	if (xf86LoadSubModule(pScrn,"int10")) {
6247104f784Smrg	    pSmi->pInt10 = xf86InitInt10(pEnt->index);
6257104f784Smrg	}
62609885543Smrg
6277104f784Smrg	if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
6287104f784Smrg	    pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
6297104f784Smrg	}
63009885543Smrg
6317104f784Smrg	if(!pSmi->pVbe){
6327104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n");
6337104f784Smrg	    pSmi->useBIOS = FALSE;
6347104f784Smrg	}
63509885543Smrg    }
63609885543Smrg
637b698ba48Smrg#ifndef XSERVER_LIBPCIACCESS
63809885543Smrg    xf86RegisterResources(pEnt->index, NULL, ResExclusive);
639b698ba48Smrg#endif
64009885543Smrg    /*
64109885543Smrg     * Set the Chipset and ChipRev, allowing config file entries to
64209885543Smrg     * override.
64309885543Smrg     */
64409885543Smrg    if (pEnt->device->chipset && *pEnt->device->chipset) {
64509885543Smrg	pScrn->chipset = pEnt->device->chipset;
64609885543Smrg	pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
64709885543Smrg	from = X_CONFIG;
6487104f784Smrg    }
6497104f784Smrg    else if (pEnt->device->chipID >= 0) {
65009885543Smrg	pSmi->Chipset = pEnt->device->chipID;
65109885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
65209885543Smrg	from = X_CONFIG;
65309885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
65409885543Smrg		   pSmi->Chipset);
6557104f784Smrg    }
6567104f784Smrg    else {
65709885543Smrg	from = X_PROBED;
6587104f784Smrg	pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
65909885543Smrg	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
66009885543Smrg    }
66109885543Smrg
66209885543Smrg    if (pEnt->device->chipRev >= 0) {
66309885543Smrg	pSmi->ChipRev = pEnt->device->chipRev;
66409885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
66509885543Smrg		   pSmi->ChipRev);
66609885543Smrg    }
6677104f784Smrg    else
6687104f784Smrg        pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo);
6697b58d2e0Smrg    free(pEnt);
67009885543Smrg
67109885543Smrg    /*
67209885543Smrg     * This shouldn't happen because such problems should be caught in
67309885543Smrg     * SMI_Probe(), but check it just in case.
67409885543Smrg     */
67509885543Smrg    if (pScrn->chipset == NULL) {
67609885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
67709885543Smrg				"recognised\n", pSmi->Chipset);
6787104f784Smrg	LEAVE(FALSE);
67909885543Smrg    }
68009885543Smrg
68109885543Smrg    if (pSmi->Chipset < 0) {
68209885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
68309885543Smrg		   "recognised\n", pScrn->chipset);
6847104f784Smrg	LEAVE(FALSE);
68509885543Smrg    }
68609885543Smrg
68709885543Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
68809885543Smrg
6897104f784Smrg#ifndef XSERVER_LIBPCIACCESS
69009885543Smrg    pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
69109885543Smrg		   	  pSmi->PciInfo->func);
6927104f784Smrg#endif
69309885543Smrg
6947104f784Smrg    from = X_DEFAULT;
6957104f784Smrg    if(pSmi->Chipset == SMI_LYNX3DM &&
6967104f784Smrg       pScrn->bitsPerPixel == 16)
69709885543Smrg	pSmi->Dualhead = TRUE;
6987104f784Smrg    else
6997104f784Smrg	pSmi->Dualhead = FALSE;
7007104f784Smrg
7017104f784Smrg    if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead))
7027104f784Smrg	from = X_CONFIG;
7037104f784Smrg
7047104f784Smrg    if (IS_MSOC(pSmi)) {
7057104f784Smrg	pSmi->lcd = TRUE;
7067104f784Smrg	if (pSmi->Dualhead && pSmi->UseFBDev) {
7077104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7087104f784Smrg		       "Dual head disabled in fbdev mode\n");
7097104f784Smrg	    pSmi->Dualhead = FALSE;
7107104f784Smrg	}
7117104f784Smrg	/* FIXME Randr cursor code only works properly when argb cursors
7127104f784Smrg	 * are also supported.
7137104f784Smrg	 * FIXME This probably is a randr cursor bug, and since access to
7147104f784Smrg	 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor
7157104f784Smrg	 * field is not available, one cannot easily workaround the problem,
7167104f784Smrg	 * so, just disable it...
7177104f784Smrg	 * TODO Check with a X Server newer then 1.4.0.90 (that is being
7187104f784Smrg	 * used in the 502 OEM image).
7197104f784Smrg	 * */
7207104f784Smrg	if (pSmi->Dualhead && pSmi->HwCursor) {
7217104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
7227104f784Smrg		       "HW Cursor disabled in dual head mode\n");
7237104f784Smrg	    pSmi->HwCursor = FALSE;
7247104f784Smrg	}
7257104f784Smrg    }
7267104f784Smrg    else if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
7277104f784Smrg	/* tweak options for dualhead */
7287104f784Smrg	if (pSmi->Dualhead) {
7297104f784Smrg	    pSmi->useBIOS = FALSE;
7307104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n");
7317104f784Smrg	    pSmi->HwCursor = FALSE;
7327104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n");
7337104f784Smrg	    if (pScrn->bitsPerPixel != 16) {
7347104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at "
7357104f784Smrg			   "depth 16\n");
7367104f784Smrg		LEAVE(FALSE);
7377104f784Smrg	    }
7387104f784Smrg	}
73909885543Smrg    }
7407104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n",
7417104f784Smrg	       pSmi->Dualhead ? "en" : "dis");
74209885543Smrg
7437104f784Smrg    if (!pSmi->NoAccel) {
7447104f784Smrg	char *strptr;
7457104f784Smrg
7467104f784Smrg	from = X_DEFAULT;
7475805b606Smacallan	pSmi->useEXA = TRUE;
7487104f784Smrg	if ((strptr = (char *)xf86GetOptValString(pSmi->Options,
7497104f784Smrg						  OPTION_ACCELMETHOD))) {
7507104f784Smrg	    if (!xf86NameCmp(strptr,"XAA")) {
7517104f784Smrg		from = X_CONFIG;
7527104f784Smrg		pSmi->useEXA = FALSE;
7537104f784Smrg	    } else if(!xf86NameCmp(strptr,"EXA")) {
7547104f784Smrg		from = X_CONFIG;
7557104f784Smrg		pSmi->useEXA = TRUE;
7567104f784Smrg	    }
75709885543Smrg	}
7587104f784Smrg
7597104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
7607104f784Smrg		pSmi->useEXA ? "EXA" : "XAA");
76109885543Smrg    }
76209885543Smrg
7637104f784Smrg    if (IS_MSOC(pSmi)) {
7647104f784Smrg	pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead;
7657104f784Smrg	from = X_DEFAULT;
7667104f784Smrg	if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) {
7677104f784Smrg	    from = X_CONFIG;
7687104f784Smrg
7697104f784Smrg	    /* FIXME */
7707104f784Smrg	    if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) {
7717104f784Smrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
7727104f784Smrg			   "CSCVideo requires XAA or EXA in single head mode.\n");
7737104f784Smrg		pSmi->CSCVideo = FALSE;
7747104f784Smrg	    }
7757104f784Smrg	}
77609885543Smrg
7777104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n",
7787104f784Smrg		   pSmi->CSCVideo ? "en" : "dis");
7797104f784Smrg    }
78009885543Smrg
7817104f784Smrg    SMI_MapMmio(pScrn);
7827104f784Smrg    SMI_DetectMem(pScrn);
7837104f784Smrg    SMI_MapMem(pScrn);
7847104f784Smrg    SMI_DisableVideo(pScrn);
78509885543Smrg
78609885543Smrg    /* detect the panel size */
78709885543Smrg    SMI_DetectPanelSize(pScrn);
78809885543Smrg
7897104f784Smrg    if(!IS_MSOC(pSmi)){
7907104f784Smrg	if (xf86LoadSubModule(pScrn, "i2c")) {
7917104f784Smrg	    SMI_I2CInit(pScrn);
7927104f784Smrg	}
7932ec8c4b4Smrg	xf86LoadSubModule(pScrn, "ddc");
79409885543Smrg    }
79509885543Smrg
79609885543Smrg    /*
79709885543Smrg     * If the driver can do gamma correction, it should call xf86SetGamma()
79809885543Smrg     */
79909885543Smrg    {
80009885543Smrg	Gamma zeros = { 0.0, 0.0, 0.0 };
80109885543Smrg
80209885543Smrg	if (!xf86SetGamma(pScrn, zeros)) {
80309885543Smrg	    SMI_EnableVideo(pScrn);
80409885543Smrg	    SMI_UnmapMem(pScrn);
8057104f784Smrg	    LEAVE(FALSE);
80609885543Smrg	}
80709885543Smrg    }
80809885543Smrg
8097104f784Smrg    SMI_DetectMCLK(pScrn);
81009885543Smrg
81109885543Smrg    /*
81209885543Smrg     * Setup the ClockRanges, which describe what clock ranges are available,
81309885543Smrg     * and what sort of modes they can be used for.
81409885543Smrg     */
8157104f784Smrg    pSmi->clockRange.next = NULL;
8167104f784Smrg    pSmi->clockRange.minClock = 20000;
81709885543Smrg
8187104f784Smrg    if (SMI_LYNXM_SERIES(pSmi->Chipset) ||
8197104f784Smrg	IS_MSOC(pSmi))
8207104f784Smrg	pSmi->clockRange.maxClock = 200000;
82109885543Smrg    else
8227104f784Smrg        pSmi->clockRange.maxClock = 135000;
82309885543Smrg
8247104f784Smrg    pSmi->clockRange.clockIndex = -1;
8257104f784Smrg    pSmi->clockRange.interlaceAllowed = FALSE;
8267104f784Smrg    pSmi->clockRange.doubleScanAllowed = FALSE;
82709885543Smrg
8287104f784Smrg    if(!SMI_CrtcPreInit(pScrn))
8297104f784Smrg	LEAVE(FALSE);
8307104f784Smrg
8317104f784Smrg    if(!SMI_OutputPreInit(pScrn))
8327104f784Smrg	LEAVE(FALSE);
8337104f784Smrg
8347104f784Smrg    /* Only allow growing the screen dimensions if EXA is being used */
8357104f784Smrg    if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){
83609885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
8372ec8c4b4Smrg
8382ec8c4b4Smrg	SMI_EnableVideo(pScrn);
8392ec8c4b4Smrg	SMI_UnmapMem(pScrn);
8407104f784Smrg	LEAVE(FALSE);
84109885543Smrg    }
84209885543Smrg
8432ec8c4b4Smrg    /* Ensure that the framebuffer size just set fits in video memory. */
8442ec8c4b4Smrg    {
8452ec8c4b4Smrg	int aligned_pitch = (pScrn->virtualX*pSmi->Bpp + 15) & ~15;
8462ec8c4b4Smrg
8472ec8c4b4Smrg	if(aligned_pitch * pScrn->virtualY > pSmi->FBReserved){
8482ec8c4b4Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video memory "
8492ec8c4b4Smrg		       "for the configured screen size (%dx%d) and color depth.\n",
8502ec8c4b4Smrg                       pScrn->virtualX, pScrn->virtualY);
8512ec8c4b4Smrg
8522ec8c4b4Smrg	    SMI_EnableVideo(pScrn);
8532ec8c4b4Smrg	    SMI_UnmapMem(pScrn);
8542ec8c4b4Smrg	    LEAVE(FALSE);
8552ec8c4b4Smrg	}
8562ec8c4b4Smrg    }
8572ec8c4b4Smrg
85809885543Smrg
8597104f784Smrg    SMI_EnableVideo(pScrn);
8607104f784Smrg    SMI_UnmapMem(pScrn);
8617104f784Smrg
8627104f784Smrg    if(pSmi->pVbe){
8637104f784Smrg       vbeFree(pSmi->pVbe);
8647104f784Smrg       pSmi->pVbe = NULL;
8657104f784Smrg    }
8667104f784Smrg    if(pSmi->pInt10){
8677104f784Smrg       xf86FreeInt10(pSmi->pInt10);
8687104f784Smrg       pSmi->pInt10 = NULL;
8697104f784Smrg    }
87009885543Smrg
87109885543Smrg    /* Set display resolution */
87209885543Smrg    xf86SetDpi(pScrn, 0, 0);
87309885543Smrg
8747104f784Smrg    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
87509885543Smrg	SMI_FreeRec(pScrn);
8767104f784Smrg	LEAVE(FALSE);
87709885543Smrg    }
87809885543Smrg
87909885543Smrg    /* Load XAA or EXA if needed */
88009885543Smrg    if (!pSmi->NoAccel) {
88109885543Smrg	if (!pSmi->useEXA) {
88209885543Smrg	    if (!xf86LoadSubModule(pScrn, "xaa")) {
8835788ca14Smrg		xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration\n");
8845788ca14Smrg		pSmi->NoAccel = 1;
88509885543Smrg	    }
88609885543Smrg	} else {
88709885543Smrg	    XF86ModReqInfo req;
88809885543Smrg	    int errmaj, errmin;
88909885543Smrg
89009885543Smrg	    memset(&req, 0, sizeof(XF86ModReqInfo));
89109885543Smrg	    req.majorversion = 2;
8927104f784Smrg	    req.minorversion = 1;
89309885543Smrg
89409885543Smrg	    if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
89509885543Smrg				&req, &errmaj, &errmin)) {
89609885543Smrg		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
89709885543Smrg		SMI_FreeRec(pScrn);
8987104f784Smrg		LEAVE(FALSE);
89909885543Smrg	    }
90009885543Smrg	}
90109885543Smrg    }
90209885543Smrg
90309885543Smrg    /* Load ramdac if needed */
9047104f784Smrg    if (pSmi->HwCursor) {
90509885543Smrg	if (!xf86LoadSubModule(pScrn, "ramdac")) {
90609885543Smrg	    SMI_FreeRec(pScrn);
9077104f784Smrg	    LEAVE(FALSE);
90809885543Smrg	}
90909885543Smrg    }
91009885543Smrg
9117104f784Smrg    LEAVE(TRUE);
91209885543Smrg}
91309885543Smrg
91409885543Smrg/*
91509885543Smrg * This is called when VT switching back to the X server.  Its job is to
91609885543Smrg * reinitialise the video mode. We may wish to unmap video/MMIO memory too.
91709885543Smrg */
91809885543Smrg
91909885543Smrgstatic Bool
9205788ca14SmrgSMI_EnterVT(VT_FUNC_ARGS_DECL)
92109885543Smrg{
9225788ca14Smrg    SCRN_INFO_PTR(arg);
92309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
92409885543Smrg
9257104f784Smrg    ENTER();
92609885543Smrg
92709885543Smrg    /* Enable MMIO and map memory */
92809885543Smrg    SMI_MapMem(pScrn);
92909885543Smrg
9307104f784Smrg    pSmi->Save(pScrn);
93109885543Smrg
9327104f784Smrg    /* FBBase may have changed after remapping the memory */
9337104f784Smrg    pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
9347104f784Smrg				       -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
9357b58d2e0Smrg#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0))
9367104f784Smrg    pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
9377b58d2e0Smrg#endif
93809885543Smrg
9397104f784Smrg    if(pSmi->useEXA)
9407104f784Smrg       pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
94109885543Smrg
9427104f784Smrg    /* Do the CRTC independent initialization */
9437104f784Smrg    if(!SMI_HWInit(pScrn))
9447104f784Smrg	LEAVE(FALSE);
94509885543Smrg
9467104f784Smrg    /* Initialize the chosen modes */
9477104f784Smrg    if (!xf86SetDesiredModes(pScrn))
9487104f784Smrg	LEAVE(FALSE);
94909885543Smrg
9507104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
9517104f784Smrg		   "Done writing mode.  Register dump:\n");
9527104f784Smrg    SMI_PrintRegs(pScrn);
95309885543Smrg
95409885543Smrg    /* Reset the grapics engine */
95509885543Smrg    if (!pSmi->NoAccel)
95609885543Smrg	SMI_EngineReset(pScrn);
95709885543Smrg
9587104f784Smrg    LEAVE(TRUE);
95909885543Smrg}
96009885543Smrg
96109885543Smrg/*
96209885543Smrg * This is called when VT switching away from the X server.  Its job is to
96309885543Smrg * restore the previous (text) mode. We may wish to remap video/MMIO memory
96409885543Smrg * too.
96509885543Smrg */
96609885543Smrg
96709885543Smrgstatic void
9685788ca14SmrgSMI_LeaveVT(VT_FUNC_ARGS_DECL)
96909885543Smrg{
9705788ca14Smrg    SCRN_INFO_PTR(arg);
9717104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
97209885543Smrg
9737104f784Smrg    ENTER();
97409885543Smrg
9757104f784Smrg    SMI_AccelSync(pScrn);
97609885543Smrg
9777104f784Smrg    /* Ensure that the rotation BlockHandler is unwrapped, and the shadow
9787104f784Smrg       pixmaps are deallocated, as the video memory is going to be
9797104f784Smrg       unmapped.  */
9807104f784Smrg    xf86RotateCloseScreen(pScrn->pScreen);
98109885543Smrg
9827104f784Smrg    /* Pixmaps that by chance get allocated near the former aperture
9837104f784Smrg       address shouldn't be considered offscreen. */
9847104f784Smrg    if(pSmi->useEXA)
9857104f784Smrg       pSmi->EXADriverPtr->memoryBase=NULL;
98609885543Smrg
9877104f784Smrg    /* Clear frame buffer */
9887104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
9897104f784Smrg
9907104f784Smrg    if (!IS_MSOC(pSmi)) {
9917104f784Smrg	vgaHWPtr	hwp = VGAHWPTR(pScrn);
9927104f784Smrg
9937104f784Smrg	SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
99409885543Smrg    }
9957104f784Smrg    else
9967104f784Smrg	SMI501_WriteMode(pScrn, pSmi->save);
99709885543Smrg
99809885543Smrg    SMI_UnmapMem(pScrn);
99909885543Smrg
10007104f784Smrg    LEAVE();
100109885543Smrg}
100209885543Smrg
100309885543Smrgstatic void
10047104f784SmrgSMI_DetectPanelSize(ScrnInfoPtr pScrn)
100509885543Smrg{
1006621ff18cSmrg    const char	*s;
10077104f784Smrg    int		 width, height;
10087104f784Smrg    SMIPtr	 pSmi = SMIPTR(pScrn);
100909885543Smrg
10107104f784Smrg    pSmi->lcdWidth  = 0;
10117104f784Smrg    pSmi->lcdHeight = 0;
10127104f784Smrg    if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) {
10137104f784Smrg	if (sscanf(s, "%dx%d", &width, &height) != 2)
10147104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
10157104f784Smrg		       "Invalid PanelSize option: %s\n", s);
10167104f784Smrg	else {
10177104f784Smrg	    pSmi->lcdWidth  = width;
10187104f784Smrg	    pSmi->lcdHeight = height;
101909885543Smrg	}
102009885543Smrg    }
102109885543Smrg
10227104f784Smrg    if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) {
10237104f784Smrg	/* panel size detection ... requires BIOS call on 730 hardware */
1024eb3dced6Smacallan#ifdef USE_INT10
10257104f784Smrg	if (pSmi->Chipset == SMI_COUGAR3DR) {
10267104f784Smrg	    if (pSmi->pInt10 != NULL) {
10277104f784Smrg		pSmi->pInt10->num = 0x10;
10287104f784Smrg		pSmi->pInt10->ax  = 0x5F00;
10297104f784Smrg		pSmi->pInt10->bx  = 0;
10307104f784Smrg		pSmi->pInt10->cx  = 0;
10317104f784Smrg		pSmi->pInt10->dx  = 0;
10327104f784Smrg		xf86ExecX86int10(pSmi->pInt10);
10337104f784Smrg		if (pSmi->pInt10->ax == 0x005F) {
10347104f784Smrg		    switch (pSmi->pInt10->cx & 0x0F) {
10357104f784Smrg			case PANEL_640x480:
10367104f784Smrg			    pSmi->lcdWidth  = 640;
10377104f784Smrg			    pSmi->lcdHeight = 480;
10387104f784Smrg			    break;
10397104f784Smrg			case PANEL_800x600:
10407104f784Smrg			    pSmi->lcdWidth  = 800;
10417104f784Smrg			    pSmi->lcdHeight = 600;
10427104f784Smrg			    break;
10437104f784Smrg			case PANEL_1024x768:
10447104f784Smrg			    pSmi->lcdWidth  = 1024;
10457104f784Smrg			    pSmi->lcdHeight = 768;
10467104f784Smrg			    break;
10477104f784Smrg			case PANEL_1280x1024:
10487104f784Smrg			    pSmi->lcdWidth  = 1280;
10497104f784Smrg			    pSmi->lcdHeight = 1024;
10507104f784Smrg			    break;
10517104f784Smrg			case PANEL_1600x1200:
10527104f784Smrg			    pSmi->lcdWidth  = 1600;
10537104f784Smrg			    pSmi->lcdHeight = 1200;
10547104f784Smrg			    break;
10557104f784Smrg			case PANEL_1400x1050:
10567104f784Smrg			    pSmi->lcdWidth  = 1400;
10577104f784Smrg			    pSmi->lcdHeight = 1050;
10587104f784Smrg			    break;
10597104f784Smrg		    }
106009885543Smrg
10617104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10627104f784Smrg			       "Detected panel size via BIOS: %d x %d\n",
10637104f784Smrg			       pSmi->lcdWidth, pSmi->lcdHeight);
106409885543Smrg		}
10657104f784Smrg		else
10667104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10677104f784Smrg			       "BIOS error during 730 panel detection!\n");
106809885543Smrg	    }
10697104f784Smrg	    else  {
10707104f784Smrg		/* int10 support isn't setup on the second call to this function,
10717104f784Smrg		  o if this is the second call, don't do detection again */
10727104f784Smrg		if (pSmi->lcd == 0)
10737104f784Smrg		    /* If we get here, int10 support is not loaded or not working */
10747104f784Smrg		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
10757104f784Smrg			       "No BIOS support for 730 panel detection!\n");
107609885543Smrg	    }
107709885543Smrg
10787104f784Smrg	    /* Set this to indicate that we've done the detection */
10797104f784Smrg	    pSmi->lcd = 1;
108009885543Smrg	}
1081eb3dced6Smacallan	else
1082eb3dced6Smacallan#endif /* USE_INT10 */
1083eb3dced6Smacallan	if (IS_MSOC(pSmi)) {
10847104f784Smrg	    pSmi->lcdWidth  = (READ_SCR(pSmi, PANEL_WWIDTH)  >> 16) & 2047;
10857104f784Smrg	    pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047;
108609885543Smrg	}
10877104f784Smrg	else {
10887104f784Smrg	    /* panel size detection for hardware other than 730 */
10897104f784Smrg	    pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10907104f784Smrg				     0x31) & 0x01;
109109885543Smrg
10927104f784Smrg	    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10937104f784Smrg			     0x30) & 0x01) {
10947104f784Smrg		pSmi->lcd <<= 1;
10957104f784Smrg	    }
10967104f784Smrg	    switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
10977104f784Smrg				 0x30) & 0x0C) {
10987104f784Smrg		case 0x00:
109909885543Smrg		    pSmi->lcdWidth  = 640;
110009885543Smrg		    pSmi->lcdHeight = 480;
110109885543Smrg		    break;
11027104f784Smrg		case 0x04:
110309885543Smrg		    pSmi->lcdWidth  = 800;
110409885543Smrg		    pSmi->lcdHeight = 600;
110509885543Smrg		    break;
11067104f784Smrg		case 0x08:
11077104f784Smrg		    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
11087104f784Smrg				     0x74) & 0x02) {
11097104f784Smrg			pSmi->lcdWidth  = 1024;
11107104f784Smrg			pSmi->lcdHeight = 600;
11117104f784Smrg		    }
11127104f784Smrg		    else {
11137104f784Smrg			pSmi->lcdWidth  = 1024;
11147104f784Smrg			pSmi->lcdHeight = 768;
11157104f784Smrg		    }
111609885543Smrg		    break;
11177104f784Smrg		case 0x0C:
111809885543Smrg		    pSmi->lcdWidth  = 1280;
111909885543Smrg		    pSmi->lcdHeight = 1024;
112009885543Smrg		    break;
112109885543Smrg	    }
112209885543Smrg	}
112309885543Smrg    }
112409885543Smrg
11257104f784Smrg    if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0)
11267104f784Smrg	pSmi->lcdWidth = 1024;
11277104f784Smrg    if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0)
11287104f784Smrg	pSmi->lcdHeight = 768;
11297104f784Smrg
113009885543Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
113109885543Smrg	       (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
113209885543Smrg	       pSmi->lcdWidth, pSmi->lcdHeight);
113309885543Smrg
113409885543Smrg}
113509885543Smrg
11367104f784Smrgstatic void
11377104f784SmrgSMI_DetectMCLK(ScrnInfoPtr pScrn)
11387104f784Smrg{
11397104f784Smrg    double		real;
11407104f784Smrg    MSOCClockRec	clock;
11417104f784Smrg    int			mclk, mxclk;
11427104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
11437104f784Smrg
11447104f784Smrg    /* MCLK defaults */
11457104f784Smrg    if (pSmi->Chipset == SMI_LYNXEMplus){
11467104f784Smrg	/* The SM712 can be safely clocked up to 157MHz, according to
11477104f784Smrg	   Silicon Motion engineers. */
11487104f784Smrg	pSmi->MCLK = 157000;
11497104f784Smrg
11502ec8c4b4Smrg    } else if (IS_MSOC(pSmi)) {
11512ec8c4b4Smrg       /* Set some sane defaults for the clock settings if we are on a
11522ec8c4b4Smrg          SM502 and it's likely to be uninitialized. */
11532ec8c4b4Smrg
11542ec8c4b4Smrg       if (!xf86IsPrimaryPci(pSmi->PciInfo) &&
11552ec8c4b4Smrg           (READ_SCR(pSmi, DEVICE_ID) & 0xFF) >= 0xC0) {
11562ec8c4b4Smrg          pSmi->MCLK = 112000;
11572ec8c4b4Smrg          pSmi->MXCLK = 144000;
11582ec8c4b4Smrg       }
11592ec8c4b4Smrg
11602ec8c4b4Smrg    } else {
11612ec8c4b4Smrg        pSmi->MCLK = 0;
11622ec8c4b4Smrg        pSmi->MXCLK = 0;
11632ec8c4b4Smrg    }
11647104f784Smrg
11657104f784Smrg    /* MCLK from user settings */
11667104f784Smrg    if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
11677104f784Smrg	if (IS_MSOC(pSmi) || (int)real <= 120) {
11687104f784Smrg	    pSmi->MCLK = (int)(real * 1000.0);
11697104f784Smrg	} else {
11707104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
11717104f784Smrg		       "Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
11727104f784Smrg		       real);
11737104f784Smrg	}
11747104f784Smrg    }
11757104f784Smrg    mclk = pSmi->MCLK;
11767104f784Smrg
11777104f784Smrg    if (IS_MSOC(pSmi)) {
11787104f784Smrg	clock.value = READ_SCR(pSmi, CURRENT_CLOCK);
11797104f784Smrg	if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK,
11807104f784Smrg			      OPTUNITS_MHZ, &real))
11817104f784Smrg	    pSmi->MXCLK = (int)(real * 1000.0);
11827104f784Smrg    }
11837104f784Smrg
11847104f784Smrg    /* Already programmed MCLK */
11857104f784Smrg    if (pSmi->MCLK == 0) {
11867104f784Smrg	if (IS_MSOC(pSmi))
11877104f784Smrg	    mclk = ((clock.f.m_select ? 336 : 288) /
11887104f784Smrg		    ((clock.f.m_divider ? 3 : 1) <<
11897104f784Smrg		     (unsigned)clock.f.m_shift)) * 1000;
11907104f784Smrg	else {
11917104f784Smrg	    unsigned char	shift, m, n;
11927104f784Smrg
11937104f784Smrg	    m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
11947104f784Smrg	    n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
11957104f784Smrg	    switch (n >> 6) {
11967104f784Smrg		case 1:
11977104f784Smrg		    shift = 4;
11987104f784Smrg		    break;
11997104f784Smrg		case 2:
12007104f784Smrg		    shift = 2;
12017104f784Smrg		    break;
12027104f784Smrg		default:
12037104f784Smrg		    shift = 1;
12047104f784Smrg		    break;
12057104f784Smrg	    }
12067104f784Smrg	    n &= 0x3F;
12077104f784Smrg	    mclk = ((1431818 * m) / n / shift + 50) / 100;
12087104f784Smrg	}
12097104f784Smrg    }
12107104f784Smrg
12117104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0);
12127104f784Smrg    if (IS_MSOC(pSmi)) {
12137104f784Smrg	if (pSmi->MXCLK == 0) {
12147104f784Smrg	    mxclk = ((clock.f.m1_select ? 336 : 288) /
12157104f784Smrg		     ((clock.f.m1_divider ? 3 : 1) <<
12167104f784Smrg		      (unsigned)clock.f.m1_shift)) * 1000;
12177104f784Smrg	}
12187104f784Smrg	else
12197104f784Smrg	    mxclk = pSmi->MXCLK;
12207104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0);
12217104f784Smrg    }
12227104f784Smrg}
12237104f784Smrg
122409885543Smrgstatic Bool
12257104f784SmrgSMI_MapMmio(ScrnInfoPtr pScrn)
122609885543Smrg{
12277104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
12287104f784Smrg    CARD32	memBase;
122909885543Smrg
12307104f784Smrg    SMI_EnableMmio(pScrn);
123109885543Smrg
123209885543Smrg    switch (pSmi->Chipset) {
12337104f784Smrg	case SMI_COUGAR3DR:
12347104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
12357104f784Smrg	    pSmi->MapSize = 0x200000;
12367104f784Smrg	    break;
12377104f784Smrg	case SMI_LYNX3D:
12387104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000;
12397104f784Smrg	    pSmi->MapSize = 0x180000;
12407104f784Smrg	    break;
12417104f784Smrg	case SMI_LYNXEM:
12427104f784Smrg	case SMI_LYNXEMplus:
12437104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
12447104f784Smrg	    pSmi->MapSize = 0x400000;
12457104f784Smrg	    break;
12467104f784Smrg	case SMI_LYNX3DM:
12477104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
12487104f784Smrg	    pSmi->MapSize = 0x200000;
12497104f784Smrg	    break;
12507104f784Smrg	case SMI_MSOC:
12517104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
12527104f784Smrg	    pSmi->MapSize = 0x200000;
12537104f784Smrg	    break;
12547104f784Smrg	default:
12557104f784Smrg	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
12567104f784Smrg	    pSmi->MapSize = 0x10000;
12577104f784Smrg	    break;
125809885543Smrg    }
12597104f784Smrg
12607104f784Smrg#ifndef XSERVER_LIBPCIACCESS
126109885543Smrg    pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
126209885543Smrg				  memBase, pSmi->MapSize);
12637104f784Smrg#else
12647104f784Smrg    {
12657104f784Smrg	void	**result = (void**)&pSmi->MapBase;
12667104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
12677104f784Smrg					     memBase,
12687104f784Smrg					     pSmi->MapSize,
12697104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE,
12707104f784Smrg					     result);
12717104f784Smrg
12727104f784Smrg	if (err)
1273eb3dced6Smacallan	    pSmi->MapBase = NULL;
12747104f784Smrg    }
12757104f784Smrg#endif
127609885543Smrg
127709885543Smrg    if (pSmi->MapBase == NULL) {
127809885543Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
127909885543Smrg		   "MMIO registers.\n");
12807104f784Smrg	return (FALSE);
128109885543Smrg    }
128209885543Smrg
128309885543Smrg    switch (pSmi->Chipset) {
12847104f784Smrg	case SMI_COUGAR3DR:
12857104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
12867104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
12877104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
12887104f784Smrg	    pSmi->FPRBase = pSmi->MapBase + 0x005800;
12897104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
12907104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
12917104f784Smrg	    pSmi->DataPortSize = 0x100000;
12927104f784Smrg	    break;
12937104f784Smrg	case SMI_LYNX3D:
12947104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
12957104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
12967104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
12977104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x040000;
12987104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x080000;
12997104f784Smrg	    pSmi->DataPortSize = 0x100000;
13007104f784Smrg	    break;
13017104f784Smrg	case SMI_LYNXEM:
13027104f784Smrg	case SMI_LYNXEMplus:
13037104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x008000;
13047104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x00C000;
13057104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x00E000;
13067104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x300000;
13077104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
13087104f784Smrg	    pSmi->DataPortSize = 0x8000 /*0x200000*/;
13097104f784Smrg	    break;
13107104f784Smrg	case SMI_LYNX3DM:
13117104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
13127104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
13137104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
13147104f784Smrg	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
13157104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
13167104f784Smrg	    pSmi->DataPortSize = 0x100000;
13177104f784Smrg	    break;
13187104f784Smrg	case SMI_MSOC:
13197104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x100000;
13207104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0x000000;
13217104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0x090000;
13227104f784Smrg	    pSmi->DCRBase = pSmi->MapBase + 0x080000;
13237104f784Smrg	    pSmi->SCRBase = pSmi->MapBase + 0x000000;
13247104f784Smrg	    pSmi->IOBase = 0;
13257104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase + 0x110000;
13267104f784Smrg	    pSmi->DataPortSize = 0x10000;
13277104f784Smrg	    break;
13287104f784Smrg	default:
13297104f784Smrg	    pSmi->DPRBase = pSmi->MapBase + 0x8000;
13307104f784Smrg	    pSmi->VPRBase = pSmi->MapBase + 0xC000;
13317104f784Smrg	    pSmi->CPRBase = pSmi->MapBase + 0xE000;
13327104f784Smrg	    pSmi->IOBase  = NULL;
13337104f784Smrg	    pSmi->DataPortBase = pSmi->MapBase;
13347104f784Smrg	    pSmi->DataPortSize = 0x8000;
13357104f784Smrg	    break;
133609885543Smrg    }
13377104f784Smrg
133809885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
133909885543Smrg		   "Physical MMIO at 0x%08lX\n", (unsigned long)memBase);
134009885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
134109885543Smrg		   "Logical MMIO at %p - %p\n", pSmi->MapBase,
134209885543Smrg		   pSmi->MapBase + pSmi->MapSize - 1);
134309885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
134409885543Smrg		   "DPR=%p, VPR=%p, IOBase=%p\n",
134509885543Smrg		   pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase);
134609885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
134709885543Smrg		   "DataPort=%p - %p\n", pSmi->DataPortBase,
134809885543Smrg		   pSmi->DataPortBase + pSmi->DataPortSize - 1);
134909885543Smrg
13507104f784Smrg    return (TRUE);
13517104f784Smrg}
135209885543Smrg
13532ec8c4b4Smrg/* HACK - In some cases the BIOS hasn't filled in the "scratchpad
13542ec8c4b4Smrg   registers" (SR71) with the right amount of memory installed (e.g. MIPS
13552ec8c4b4Smrg   platform). Probe it manually. */
13562ec8c4b4Smrgstatic unsigned long
13572ec8c4b4SmrgSMI_ProbeMem(ScrnInfoPtr pScrn, unsigned long mem_skip, unsigned long mem_max)
13582ec8c4b4Smrg{
13592ec8c4b4Smrg    SMIPtr pSmi = SMIPTR(pScrn);
13602ec8c4b4Smrg    unsigned long mem_probe = 1024*1024;
13612ec8c4b4Smrg    unsigned long aperture_base;
13622ec8c4b4Smrg    void* mem;
13632ec8c4b4Smrg
13642ec8c4b4Smrg    ENTER();
13652ec8c4b4Smrg
13662ec8c4b4Smrg    aperture_base = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + mem_skip;
13672ec8c4b4Smrg    mem_max = min(mem_max , PCI_REGION_SIZE(pSmi->PciInfo, 0) - mem_skip);
13682ec8c4b4Smrg
13692ec8c4b4Smrg#ifndef XSERVER_LIBPCIACCESS
13702ec8c4b4Smrg    mem = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
13712ec8c4b4Smrg			aperture_base, mem_max);
13722ec8c4b4Smrg
13732ec8c4b4Smrg    if(!mem)
13742ec8c4b4Smrg	LEAVE(0);
13752ec8c4b4Smrg#else
13762ec8c4b4Smrg    if(pci_device_map_range(pSmi->PciInfo, aperture_base, mem_max,
13772ec8c4b4Smrg			    PCI_DEV_MAP_FLAG_WRITABLE, &mem))
13782ec8c4b4Smrg	LEAVE(0);
13792ec8c4b4Smrg#endif
13802ec8c4b4Smrg
13812ec8c4b4Smrg    while(mem_probe <= mem_max){
13822ec8c4b4Smrg	MMIO_OUT32(mem, mem_probe-4, 0x55555555);
13832ec8c4b4Smrg	if(MMIO_IN32(mem, mem_probe-4) != 0x55555555)
13842ec8c4b4Smrg	    break;
13852ec8c4b4Smrg
13862ec8c4b4Smrg	MMIO_OUT32(mem, mem_probe-4, 0xAAAAAAAA);
13872ec8c4b4Smrg	if(MMIO_IN32(mem, mem_probe-4) != 0xAAAAAAAA)
13882ec8c4b4Smrg	    break;
13892ec8c4b4Smrg
13902ec8c4b4Smrg	mem_probe <<= 1;
13912ec8c4b4Smrg    }
13922ec8c4b4Smrg
13932ec8c4b4Smrg#ifndef XSERVER_LIBPCIACCESS
13942ec8c4b4Smrg    xf86UnMapVidMem(pScrn->scrnIndex, mem, mem_max);
13952ec8c4b4Smrg#else
13962ec8c4b4Smrg    pci_device_unmap_range(pSmi->PciInfo, mem, mem_max);
13972ec8c4b4Smrg#endif
13982ec8c4b4Smrg
13992ec8c4b4Smrg    LEAVE(mem_probe >> 1);
14002ec8c4b4Smrg}
14012ec8c4b4Smrg
14027104f784Smrgstatic Bool
14037104f784SmrgSMI_DetectMem(ScrnInfoPtr pScrn)
14047104f784Smrg{
14057104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
14067104f784Smrg    MessageType from;
140709885543Smrg
14087104f784Smrg    if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){
14097104f784Smrg	pSmi->videoRAMKBytes = pScrn->videoRam;
14107104f784Smrg	from = X_CONFIG;
14117104f784Smrg    }
14127104f784Smrg    else {
14137104f784Smrg	unsigned char	 config;
14147104f784Smrg	static int	 lynx3d_table[4]  = {  0, 2, 4, 6 };
14157104f784Smrg	static int	 lynx3dm_table[4] = { 16, 2, 4, 8 };
14167104f784Smrg	static int	 msoc_table[8]    = {  4, 8, 16, 32, 64, 2, 0, 0 };
14177104f784Smrg	static int	 default_table[4] = {  1, 2, 4, 0 };
14187104f784Smrg
14197104f784Smrg	if (IS_MSOC(pSmi)) {
14207104f784Smrg	    config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7;
14217104f784Smrg	    pSmi->videoRAMKBytes = msoc_table[config] * 1024 -
14227104f784Smrg		SHARED_USB_DMA_BUFFER_SIZE;
14237104f784Smrg	}
14247104f784Smrg	else {
14257104f784Smrg	    config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
14267104f784Smrg	    switch (pSmi->Chipset) {
14277104f784Smrg		case SMI_LYNX3D:
14287104f784Smrg		    pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 +
14297104f784Smrg			512;
14307104f784Smrg		    break;
14312ec8c4b4Smrg		case SMI_LYNXEMplus:
14322ec8c4b4Smrg		    pSmi->videoRAMKBytes = SMI_ProbeMem(pScrn, 0, 0x400000) / 1024;
14332ec8c4b4Smrg		    break;
14347104f784Smrg		case SMI_LYNX3DM:
14357104f784Smrg		    pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024;
14367104f784Smrg		    break;
14377104f784Smrg		case SMI_COUGAR3DR:
14387104f784Smrg		    /* DANGER - Cougar3DR BIOS is broken - hardcode video ram
14397104f784Smrg		     * size per instructions from Silicon Motion engineers */
14407104f784Smrg		    pSmi->videoRAMKBytes = 16 * 1024;
14417104f784Smrg		    break;
14427104f784Smrg		default:
14437104f784Smrg		    pSmi->videoRAMKBytes = default_table[config >> 6] * 1024;
14447104f784Smrg		    break;
14457104f784Smrg	    }
144609885543Smrg	}
14477104f784Smrg	from = X_PROBED;
14487104f784Smrg    }
144909885543Smrg
14507104f784Smrg    pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
14517104f784Smrg    pScrn->videoRam     = pSmi->videoRAMKBytes;
14527104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, from,
14537104f784Smrg	       "videoram: %dkB\n", pSmi->videoRAMKBytes);
145409885543Smrg
14557104f784Smrg    return (TRUE);
14567104f784Smrg}
145709885543Smrg
14587104f784SmrgBool
14597104f784SmrgSMI_MapMem(ScrnInfoPtr pScrn)
14607104f784Smrg{
14617104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
14627104f784Smrg    vgaHWPtr hwp;
146309885543Smrg
14647104f784Smrg    ENTER();
14657104f784Smrg
14667104f784Smrg    if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE)
14677104f784Smrg	LEAVE(FALSE);
14687104f784Smrg
14697104f784Smrg    pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
14707104f784Smrg
14717104f784Smrg    if (pSmi->Chipset == SMI_LYNX3DM)
14727104f784Smrg	pSmi->fbMapOffset = 0x200000;
14737104f784Smrg    else
14747104f784Smrg	pSmi->fbMapOffset = 0x0;
14757104f784Smrg
14767104f784Smrg#ifndef XSERVER_LIBPCIACCESS
14777104f784Smrg    pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex,
14787104f784Smrg				 VIDMEM_FRAMEBUFFER,
14797104f784Smrg				 pSmi->PciTag,
14807104f784Smrg				 pScrn->memPhysBase + pSmi->fbMapOffset,
14817104f784Smrg				 pSmi->videoRAMBytes);
14827104f784Smrg#else
14837104f784Smrg    {
14847104f784Smrg	void	**result = (void**)&pSmi->FBBase;
14857104f784Smrg	int	  err = pci_device_map_range(pSmi->PciInfo,
14867104f784Smrg					     pScrn->memPhysBase +
14877104f784Smrg					     pSmi->fbMapOffset,
14887104f784Smrg					     pSmi->videoRAMBytes,
14897104f784Smrg					     PCI_DEV_MAP_FLAG_WRITABLE |
14907104f784Smrg					     PCI_DEV_MAP_FLAG_WRITE_COMBINE,
14917104f784Smrg					     result);
14927104f784Smrg
14937104f784Smrg	if (err)
14947104f784Smrg	    LEAVE(FALSE);
14957104f784Smrg    }
14967104f784Smrg#endif
14977104f784Smrg
14987104f784Smrg    if (pSmi->FBBase == NULL) {
14997104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
15007104f784Smrg		   "Internal error: could not map framebuffer.\n");
15017104f784Smrg	LEAVE(FALSE);
15027104f784Smrg    }
15037104f784Smrg
15047104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
15057104f784Smrg		   "Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
15067b58d2e0Smrg		   pScrn->memPhysBase, (unsigned long)pSmi->fbMapOffset);
15077104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
15087104f784Smrg		   "Logical frame buffer at %p - %p\n", pSmi->FBBase,
15097104f784Smrg		   pSmi->FBBase + pSmi->videoRAMBytes - 1);
15107104f784Smrg
15117104f784Smrg    if (IS_MSOC(pSmi)) {
15127104f784Smrg	/* Reserve space for panel cursr, and crt if in dual head mode */
15137104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
15147104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15157104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE);
15167104f784Smrg#else
15177104f784Smrg	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
15187104f784Smrg	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE);
15197104f784Smrg
15207104f784Smrg# if SMI501_CLI_DEBUG
15217104f784Smrg	if (pSmi->useEXA) {
15227104f784Smrg	    pSmi->batch_active = FALSE;
15237104f784Smrg	    pSmi->batch_length = 4096;
15247104f784Smrg	    pSmi->FBReserved -= pSmi->batch_length << 3;
15257104f784Smrg	    pSmi->batch_offset = pSmi->FBReserved;
15267104f784Smrg	    pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset);
15277104f784Smrg	    pSmi->batch_finish = -1;
15287104f784Smrg	    pSmi->batch_index = 0;
15297104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
15307104f784Smrg		       "Using command list interpreter debug code\n");
15317104f784Smrg	}
15327104f784Smrg# endif
15337104f784Smrg
15347104f784Smrg#endif
15357104f784Smrg    }
15367104f784Smrg    else {
15377104f784Smrg	/* Set up offset to hwcursor memory area, at the end of
15387104f784Smrg	 * the frame buffer.
15397104f784Smrg	 */
15407104f784Smrg	pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE;
154109885543Smrg	/* set up the fifo reserved space */
154209885543Smrg	if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ {
154309885543Smrg	    CARD32 fifoOffset = 0;
15447104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15457104f784Smrg				       0x46) << 3;
15467104f784Smrg	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15477104f784Smrg				       0x47) << 11;
15487104f784Smrg	    fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
15497104f784Smrg					0x49) & 0x1C) << 17;
155009885543Smrg	    pSmi->FBReserved = fifoOffset;	/* PDR#1074 */
155109885543Smrg	}
15527104f784Smrg	else
15537104f784Smrg	    pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
155409885543Smrg
15557104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n",
15567104f784Smrg		   (unsigned long)pSmi->FBCursorOffset);
155709885543Smrg
15587104f784Smrg	/* Assign hwp->MemBase & IOBase here */
15597104f784Smrg	hwp = VGAHWPTR(pScrn);
15607104f784Smrg	if (pSmi->IOBase != NULL)
15617104f784Smrg	    vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
15627104f784Smrg	vgaHWGetIOBase(hwp);
156309885543Smrg
15647104f784Smrg	/* Map the VGA memory when the primary video */
15657104f784Smrg	if (xf86IsPrimaryPci(pSmi->PciInfo)) {
15667104f784Smrg	    hwp->MapSize = 0x10000;
15677104f784Smrg	    if (!vgaHWMapMem(pScrn))
15687104f784Smrg		LEAVE(FALSE);
15697104f784Smrg	    pSmi->PrimaryVidMapped = TRUE;
157009885543Smrg	}
157109885543Smrg    }
157209885543Smrg
15737104f784Smrg    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n",
15747104f784Smrg	       (unsigned long)pSmi->FBReserved);
15757104f784Smrg
15767104f784Smrg    LEAVE(TRUE);
157709885543Smrg}
157809885543Smrg
157909885543Smrg/* UnMapMem - contains half of pre-4.0 EnterLeave function.  The EnterLeave
158009885543Smrg * function which en/disable access to IO ports and ext. regs
158109885543Smrg */
158209885543Smrg
15837104f784Smrgvoid
158409885543SmrgSMI_UnmapMem(ScrnInfoPtr pScrn)
158509885543Smrg{
158609885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
158709885543Smrg
15887104f784Smrg    ENTER();
158909885543Smrg
159009885543Smrg    /* Unmap VGA mem if mapped. */
159109885543Smrg    if (pSmi->PrimaryVidMapped) {
159209885543Smrg	vgaHWUnmapMem(pScrn);
159309885543Smrg	pSmi->PrimaryVidMapped = FALSE;
159409885543Smrg    }
159509885543Smrg
159609885543Smrg    SMI_DisableMmio(pScrn);
159709885543Smrg
15987104f784Smrg    if (pSmi->MapBase) {
15997104f784Smrg#ifndef XSERVER_LIBPCIACCESS
16007104f784Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase,
16017104f784Smrg			pSmi->MapSize);
16027104f784Smrg#else
16037104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase,
16047104f784Smrg			       pSmi->MapSize);
16057104f784Smrg#endif
16067104f784Smrg	pSmi->MapBase = NULL;
16077104f784Smrg    }
16087104f784Smrg
16097104f784Smrg    if (pSmi->FBBase) {
16107104f784Smrg#ifndef XSERVER_LIBPCIACCESS
161109885543Smrg	xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
161209885543Smrg			pSmi->videoRAMBytes);
16137104f784Smrg#else
16147104f784Smrg	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase,
16157104f784Smrg			       pSmi->videoRAMBytes);
16167104f784Smrg#endif
16177104f784Smrg	pSmi->FBBase = NULL;
161809885543Smrg    }
161909885543Smrg
16207104f784Smrg    LEAVE();
162109885543Smrg}
162209885543Smrg
162309885543Smrg/* This gets called at the start of each server generation. */
162409885543Smrg
162509885543Smrgstatic Bool
16265788ca14SmrgSMI_ScreenInit(SCREEN_INIT_ARGS_DECL)
162709885543Smrg{
16285788ca14Smrg    ScrnInfoPtr		pScrn = xf86ScreenToScrn(pScreen);
16297104f784Smrg    SMIPtr		pSmi = SMIPTR(pScrn);
16307104f784Smrg    EntityInfoPtr	pEnt;
163109885543Smrg
16327104f784Smrg    ENTER();
163309885543Smrg
163409885543Smrg    /* Map MMIO regs and framebuffer */
16357104f784Smrg    if (!SMI_MapMem(pScrn))
16367104f784Smrg	LEAVE(FALSE);
163709885543Smrg
163809885543Smrg    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
163909885543Smrg
16407104f784Smrg    if (!pSmi->pInt10 && pSmi->useBIOS) {
16417104f784Smrg	pSmi->pInt10 = xf86InitInt10(pEnt->index);
164209885543Smrg    }
16437104f784Smrg    if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
16447104f784Smrg	pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
164509885543Smrg    }
164609885543Smrg
16477104f784Smrg    /* Save the chip/graphics state */
16487104f784Smrg    pSmi->Save(pScrn);
164909885543Smrg
16507104f784Smrg    /* Fill in some needed pScrn fields */
16517104f784Smrg    pScrn->vtSema = TRUE;
16527104f784Smrg    pScrn->pScreen = pScreen;
165309885543Smrg
16547104f784Smrg    pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
165509885543Smrg
16567104f784Smrg    pSmi->fbArea = NULL;
16577104f784Smrg    pSmi->FBOffset = 0;
16587104f784Smrg    pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
165909885543Smrg
16607104f784Smrg    /* Clear frame buffer */
16617104f784Smrg    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
166209885543Smrg
166309885543Smrg    /*
16647104f784Smrg     * The next step is to setup the screen's visuals, and initialise the
16657104f784Smrg     * framebuffer code.  In cases where the framebuffer's default choises for
16667104f784Smrg     * things like visual layouts and bits per RGB are OK, this may be as simple
16677104f784Smrg     * as calling the framebuffer's ScreenInit() function.  If not, the visuals
16687104f784Smrg     * will need to be setup before calling a fb ScreenInit() function and fixed
16697104f784Smrg     * up after.
16707104f784Smrg     */
167109885543Smrg
16727104f784Smrg    /*
16737104f784Smrg     * Reset the visual list.
16747104f784Smrg     */
16757104f784Smrg    miClearVisualTypes();
167609885543Smrg
16777104f784Smrg    /* Setup the visuals we support. */
167809885543Smrg
16797104f784Smrg    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
16807104f784Smrg			  pScrn->rgbBits, pScrn->defaultVisual))
16817104f784Smrg	LEAVE(FALSE);
168209885543Smrg
16837104f784Smrg    if (!miSetPixmapDepths ())
16847104f784Smrg	LEAVE(FALSE);
168509885543Smrg
16867104f784Smrg    /*
16877104f784Smrg     * Call the framebuffer layer's ScreenInit function
16887104f784Smrg     */
168909885543Smrg
16907104f784Smrg    DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
16917104f784Smrg	  pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
16927104f784Smrg    if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
16937104f784Smrg		     pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
16947104f784Smrg	LEAVE(FALSE);
169509885543Smrg
16967104f784Smrg    xf86SetBlackWhitePixels(pScreen);
169709885543Smrg
16987104f784Smrg    if (pScrn->bitsPerPixel > 8) {
16997104f784Smrg	VisualPtr visual;
17007104f784Smrg	/* Fixup RGB ordering */
17017104f784Smrg	visual = pScreen->visuals + pScreen->numVisuals;
17027104f784Smrg	while (--visual >= pScreen->visuals) {
17037104f784Smrg	    if ((visual->class | DynamicClass) == DirectColor) {
17047104f784Smrg		visual->offsetRed   = pScrn->offset.red;
17057104f784Smrg		visual->offsetGreen = pScrn->offset.green;
17067104f784Smrg		visual->offsetBlue  = pScrn->offset.blue;
17077104f784Smrg		visual->redMask     = pScrn->mask.red;
17087104f784Smrg		visual->greenMask   = pScrn->mask.green;
17097104f784Smrg		visual->blueMask    = pScrn->mask.blue;
17107104f784Smrg	    }
171109885543Smrg	}
171209885543Smrg    }
171309885543Smrg
17147104f784Smrg    /* must be after RGB ordering fixed */
17157104f784Smrg    fbPictureInit(pScreen, 0, 0);
17167104f784Smrg
17177104f784Smrg    /* Do the CRTC independent initialization */
17187104f784Smrg    if(!SMI_HWInit(pScrn))
17197104f784Smrg	LEAVE(FALSE);
172009885543Smrg
17217104f784Smrg    /* Unless using EXA, regardless or using XAA or not, needs offscreen
17227104f784Smrg     * management at least for video. */
17237104f784Smrg    if (pSmi->NoAccel || !pSmi->useEXA) {
17247104f784Smrg	int		numLines;
17257104f784Smrg	BoxRec		AvailFBArea;
172609885543Smrg
17277104f784Smrg	numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
17287104f784Smrg	AvailFBArea.x1 = 0;
17297104f784Smrg	AvailFBArea.y1 = 0;
17307104f784Smrg	AvailFBArea.x2 = pScrn->virtualX;
17317104f784Smrg	AvailFBArea.y2 = numLines;
173209885543Smrg
17337104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
17347104f784Smrg		   "FrameBuffer Box: %d,%d - %d,%d\n",
17357104f784Smrg		   AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
17367104f784Smrg		   AvailFBArea.y2);
173709885543Smrg
17387104f784Smrg	xf86InitFBManager(pScreen, &AvailFBArea);
173909885543Smrg    }
174009885543Smrg
17417104f784Smrg    /* Initialize acceleration layer */
17427104f784Smrg    if (!pSmi->NoAccel) {
17437104f784Smrg	if (pSmi->useEXA && !SMI_EXAInit(pScreen))
17447104f784Smrg	    LEAVE(FALSE);
17457104f784Smrg	else if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
17467104f784Smrg	    LEAVE(FALSE);
174709885543Smrg    }
174809885543Smrg
17497104f784Smrg    /* Initialize the chosen modes */
17507104f784Smrg    if (!xf86SetDesiredModes(pScrn))
17517104f784Smrg	    LEAVE(FALSE);
175209885543Smrg
17537104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
17547104f784Smrg		   "Done writing mode.  Register dump:\n");
17557104f784Smrg    SMI_PrintRegs(pScrn);
175609885543Smrg
17577104f784Smrg#ifdef HAVE_XMODES
17587104f784Smrg    xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
17597104f784Smrg#endif
176009885543Smrg
17617104f784Smrg    /* Initialise cursor functions */
17627104f784Smrg    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
176309885543Smrg
17647104f784Smrg    /* Initialize HW cursor layer.  Must follow software cursor
17657104f784Smrg     * initialization.
17667104f784Smrg     */
17677104f784Smrg    if (pSmi->HwCursor) {
17687104f784Smrg	int	size, flags;
17697104f784Smrg
17707104f784Smrg	if (IS_MSOC(pSmi)) {
17717104f784Smrg	    size = SMI501_MAX_CURSOR;
17727104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
17737104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
17747104f784Smrg#if SMI_CURSOR_ALPHA_PLANE
17757104f784Smrg	    if (!pSmi->Dualhead)
17767104f784Smrg		flags |= HARDWARE_CURSOR_ARGB;
17777104f784Smrg#endif
17787104f784Smrg	}
17797104f784Smrg	else {
17807104f784Smrg	    size = SMILYNX_MAX_CURSOR;
17817104f784Smrg	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
17827104f784Smrg		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
17837104f784Smrg		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
17847104f784Smrg		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
17857104f784Smrg		     HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
17867104f784Smrg		     HARDWARE_CURSOR_INVERT_MASK);
17877104f784Smrg	}
178809885543Smrg
17897104f784Smrg	if (!xf86_cursors_init(pScreen, size, size, flags))
17907104f784Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
17917104f784Smrg		       "Hardware cursor initialization failed\n");
179209885543Smrg    }
179309885543Smrg
17947104f784Smrg    /* Initialise default colormap */
17957104f784Smrg    if (!miCreateDefColormap(pScreen))
17967104f784Smrg	LEAVE(FALSE);
179709885543Smrg
17987104f784Smrg    /* Initialize colormap layer.  Must follow initialization of the default
17997104f784Smrg     * colormap.  And SetGamma call, else it will load palette with solid white.
18007104f784Smrg     */
18017104f784Smrg    if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
18027104f784Smrg			     CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
18037104f784Smrg	LEAVE(FALSE);
180409885543Smrg
18057104f784Smrg    pScreen->SaveScreen = SMI_SaveScreen;
18067104f784Smrg    pSmi->CloseScreen = pScreen->CloseScreen;
18077104f784Smrg    pScreen->CloseScreen = SMI_CloseScreen;
180809885543Smrg
18097104f784Smrg    if ((IS_MSOC(pSmi) &&
18107104f784Smrg	 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
18117104f784Smrg	(!IS_MSOC(pSmi) &&
18127104f784Smrg	 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
18137104f784Smrg	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
181409885543Smrg
18157104f784Smrg    SMI_InitVideo(pScreen);
181609885543Smrg
18177104f784Smrg    if(!xf86CrtcScreenInit(pScreen))
18187104f784Smrg	LEAVE(FALSE);
181909885543Smrg
18207104f784Smrg    /* Report any unused options (only for the first generation) */
18217104f784Smrg    if (serverGeneration == 1) {
18227104f784Smrg	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
18237104f784Smrg    }
182409885543Smrg
18257104f784Smrg    LEAVE(TRUE);
182609885543Smrg}
182709885543Smrg
182809885543Smrg/*
182909885543Smrg * This is called at the end of each server generation.  It restores the
183009885543Smrg * original (text) mode.  It should also unmap the video memory, and free any
183109885543Smrg * per-generation data allocated by the driver.  It should finish by unwrapping
183209885543Smrg * and calling the saved CloseScreen function.
183309885543Smrg */
183409885543Smrg
183509885543Smrgstatic Bool
18365788ca14SmrgSMI_CloseScreen(CLOSE_SCREEN_ARGS_DECL)
183709885543Smrg{
18385788ca14Smrg    ScrnInfoPtr	pScrn = xf86ScreenToScrn(pScreen);
18397104f784Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
18407104f784Smrg    Bool	ret;
184109885543Smrg
18427104f784Smrg    ENTER();
184309885543Smrg
18447104f784Smrg    if (pSmi->HwCursor)
18457104f784Smrg	xf86_cursors_fini(pScreen);
18467104f784Smrg
18477104f784Smrg    if (pScrn->vtSema)
18487104f784Smrg	/* Restore console mode and unmap framebuffer */
18495788ca14Smrg        SMI_LeaveVT(VT_FUNC_ARGS);
185009885543Smrg
18515788ca14Smrg#ifdef HAVE_XAA_H
185209885543Smrg    if (pSmi->XAAInfoRec != NULL) {
185309885543Smrg	XAADestroyInfoRec(pSmi->XAAInfoRec);
185409885543Smrg    }
18555788ca14Smrg#endif
185609885543Smrg    if (pSmi->EXADriverPtr) {
185709885543Smrg	exaDriverFini(pScreen);
185809885543Smrg	pSmi->EXADriverPtr = NULL;
185909885543Smrg    }
18607104f784Smrg    if (pSmi->pVbe != NULL) {
18617104f784Smrg	vbeFree(pSmi->pVbe);
18627104f784Smrg	pSmi->pVbe = NULL;
186309885543Smrg    }
186409885543Smrg    if (pSmi->pInt10 != NULL) {
186509885543Smrg	xf86FreeInt10(pSmi->pInt10);
186609885543Smrg	pSmi->pInt10 = NULL;
186709885543Smrg    }
186809885543Smrg    if (pSmi->ptrAdaptor != NULL) {
18697b58d2e0Smrg	free(pSmi->ptrAdaptor);
187009885543Smrg    }
187109885543Smrg    if (pSmi->BlockHandler != NULL) {
187209885543Smrg	pScreen->BlockHandler = pSmi->BlockHandler;
187309885543Smrg    }
187409885543Smrg
187509885543Smrg    pScrn->vtSema = FALSE;
187609885543Smrg    pScreen->CloseScreen = pSmi->CloseScreen;
18775788ca14Smrg    ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
187809885543Smrg
18797104f784Smrg    LEAVE(ret);
188009885543Smrg}
188109885543Smrg
188209885543Smrgstatic void
18835788ca14SmrgSMI_FreeScreen(FREE_SCREEN_ARGS_DECL)
188409885543Smrg{
18855788ca14Smrg    SCRN_INFO_PTR(arg);
18865788ca14Smrg    SMI_FreeRec(pScrn);
188709885543Smrg}
188809885543Smrg
188909885543Smrgstatic Bool
189009885543SmrgSMI_SaveScreen(ScreenPtr pScreen, int mode)
189109885543Smrg{
18925788ca14Smrg    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
189309885543Smrg
18947104f784Smrg    ENTER();
189509885543Smrg
18967104f784Smrg    if(xf86IsUnblank(mode)){
18977104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
18987104f784Smrg    }else{
18997104f784Smrg	pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
19007104f784Smrg    }
190109885543Smrg
19027104f784Smrg    LEAVE(TRUE);
190309885543Smrg}
190409885543Smrg
190509885543Smrgvoid
1906621ff18cSmrgSMI_AdjustFrame(ADJUST_FRAME_ARGS_DECL)
190709885543Smrg{
1908621ff18cSmrg    SCRN_INFO_PTR(arg);
1909621ff18cSmrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
19107104f784Smrg    xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
191109885543Smrg
19127104f784Smrg    ENTER();
191309885543Smrg
19147104f784Smrg    SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
191509885543Smrg
19167104f784Smrg    LEAVE();
191709885543Smrg}
191809885543Smrg
191909885543SmrgBool
1920621ff18cSmrgSMI_SwitchMode(SWITCH_MODE_ARGS_DECL)
192109885543Smrg{
192209885543Smrg    Bool ret;
1923621ff18cSmrg    SCRN_INFO_PTR(arg);
19247104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
19257104f784Smrg
19267104f784Smrg    ENTER();
192709885543Smrg
19287104f784Smrg    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
192909885543Smrg
19307104f784Smrg    if (!pSmi->NoAccel)
19317104f784Smrg	SMI_EngineReset(pScrn);
193209885543Smrg
19337104f784Smrg    LEAVE(ret);
193409885543Smrg}
193509885543Smrg
193609885543Smrgvoid
19377104f784SmrgSMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
19387104f784Smrg		LOCO *colors, VisualPtr pVisual)
193909885543Smrg{
19407104f784Smrg    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
19417104f784Smrg    int crtc_idx,i,j;
19427104f784Smrg
19437104f784Smrg    ENTER();
19447104f784Smrg
19457104f784Smrg    if(pScrn->bitsPerPixel == 16){
19467104f784Smrg	/* Expand the RGB 565 palette into the 256-elements LUT */
194709885543Smrg
19487104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19497104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
195009885543Smrg
19517104f784Smrg	    for(i=0; i<numColors; i++){
19527104f784Smrg		int idx = indicies[i];
195309885543Smrg
19547104f784Smrg		if(idx<32){
19557104f784Smrg		    for(j=0; j<8; j++){
19567104f784Smrg			crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
19577104f784Smrg			crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
19587104f784Smrg		    }
19597104f784Smrg		}
19607104f784Smrg
19617104f784Smrg		for(j=0; j<4; j++)
19627104f784Smrg		    crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
19637104f784Smrg	    }
19647104f784Smrg
19657104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
196609885543Smrg    }
19677104f784Smrg    }else{
19687104f784Smrg	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
19697104f784Smrg	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
197009885543Smrg
197109885543Smrg    for(i = 0; i < numColors; i++) {
19727104f784Smrg		int idx = indicies[i];
19737104f784Smrg
19747104f784Smrg		crtcPriv->lut_r[idx] = colors[idx].red << 8;
19757104f784Smrg		crtcPriv->lut_g[idx] = colors[idx].green << 8;
19767104f784Smrg		crtcPriv->lut_b[idx] = colors[idx].blue << 8;
19777104f784Smrg	    }
19787104f784Smrg
19797104f784Smrg	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
19807104f784Smrg	}
198109885543Smrg    }
198209885543Smrg
19837104f784Smrg    LEAVE();
198409885543Smrg}
198509885543Smrg
198609885543Smrgstatic void
198709885543SmrgSMI_DisableVideo(ScrnInfoPtr pScrn)
198809885543Smrg{
198909885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
199009885543Smrg    CARD8 tmp;
199109885543Smrg
19927104f784Smrg    if (!IS_MSOC(pSmi)) {
19937104f784Smrg	if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
19947104f784Smrg	    return;
19957104f784Smrg	pSmi->DACmask = tmp;
19967104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, 0);
19977104f784Smrg    }
199809885543Smrg}
199909885543Smrg
200009885543Smrgstatic void
200109885543SmrgSMI_EnableVideo(ScrnInfoPtr pScrn)
200209885543Smrg{
200309885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
200409885543Smrg
20057104f784Smrg    if (!IS_MSOC(pSmi)) {
20067104f784Smrg	VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
20077104f784Smrg    }
200809885543Smrg}
200909885543Smrg
201009885543Smrg
201109885543Smrgvoid
201209885543SmrgSMI_EnableMmio(ScrnInfoPtr pScrn)
201309885543Smrg{
2014bbcda59bSjmcneill#if !defined(__mips__)
201509885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
201609885543Smrg
20177104f784Smrg    ENTER();
201809885543Smrg
20197104f784Smrg    if (!IS_MSOC(pSmi)) {
20207104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
20217104f784Smrg	CARD8 tmp;
20227104f784Smrg
20237104f784Smrg	/*
20247104f784Smrg	 * Enable chipset (seen on uninitialized secondary cards) might not be
20257104f784Smrg	 * needed once we use the VGA softbooter
20267104f784Smrg	 */
20277104f784Smrg	vgaHWSetStdFuncs(hwp);
202809885543Smrg
20297104f784Smrg	/* Enable linear mode */
20307104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20317104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20327104f784Smrg	pSmi->SR18Value = tmp;					/* PDR#521 */
20337104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11);
203409885543Smrg
20357104f784Smrg	/* Enable 2D/3D Engine and Video Processor */
20367104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20377104f784Smrg	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
20387104f784Smrg	pSmi->SR21Value = tmp;					/* PDR#521 */
20397104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03);
20407104f784Smrg    }
204109885543Smrg
20427104f784Smrg    LEAVE();
2043bbcda59bSjmcneill#endif
204409885543Smrg}
204509885543Smrg
204609885543Smrgvoid
204709885543SmrgSMI_DisableMmio(ScrnInfoPtr pScrn)
204809885543Smrg{
2049bbcda59bSjmcneill#if !defined(__mips__)
205009885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
205109885543Smrg
20527104f784Smrg    ENTER();
205309885543Smrg
20547104f784Smrg    if (!IS_MSOC(pSmi)) {
20557104f784Smrg	vgaHWPtr hwp = VGAHWPTR(pScrn);
205609885543Smrg
20577104f784Smrg	vgaHWSetStdFuncs(hwp);
205809885543Smrg
20597104f784Smrg	/* Disable 2D/3D Engine and Video Processor */
20607104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
20617104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value);	/* PDR#521 */
20627104f784Smrg
20637104f784Smrg	/* Disable linear mode */
20647104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
20657104f784Smrg	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value);	/* PDR#521 */
20667104f784Smrg    }
206709885543Smrg
20687104f784Smrg    LEAVE();
2069bbcda59bSjmcneill#endif
207009885543Smrg}
207109885543Smrg
207209885543Smrgstatic void
20737104f784SmrgSMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
20747104f784Smrg{
20757104f784Smrg    vbeInfoPtr pVbe;
20767104f784Smrg    if (xf86LoadSubModule(pScrn, "vbe")) {
20777104f784Smrg	pVbe = VBEInit(NULL, index);
20787104f784Smrg	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
20797104f784Smrg	vbeFree(pVbe);
20807104f784Smrg    }
20817104f784Smrg}
20827104f784Smrg
20837104f784Smrgstatic Bool
20847104f784SmrgSMI_HWInit(ScrnInfoPtr pScrn)
208509885543Smrg{
208609885543Smrg    SMIPtr pSmi = SMIPTR(pScrn);
208709885543Smrg
20887104f784Smrg    ENTER();
208909885543Smrg
20907104f784Smrg    if(IS_MSOC(pSmi))
20917104f784Smrg	LEAVE(SMI501_HWInit(pScrn));
20927104f784Smrg    else
20937104f784Smrg	LEAVE(SMILynx_HWInit(pScrn));
20947104f784Smrg}
209509885543Smrg
20967104f784Smrgvoid
20977104f784SmrgSMI_PrintRegs(ScrnInfoPtr pScrn)
20987104f784Smrg{
20997104f784Smrg    SMIPtr pSmi = SMIPTR(pScrn);
21007104f784Smrg    int i;
210109885543Smrg
21027104f784Smrg    ENTER();
210309885543Smrg
21047104f784Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
21057104f784Smrg		"START register dump ------------------\n");
21067104f784Smrg
21077104f784Smrg    if(IS_MSOC(pSmi))
21087104f784Smrg	SMI501_PrintRegs(pScrn);
21097104f784Smrg    else
21107104f784Smrg	SMILynx_PrintRegs(pScrn);
211109885543Smrg
211209885543Smrg
211309885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nDPR    x0       x4       x8       xC");
211409885543Smrg    for (i = 0x00; i <= 0x44; i += 4) {
211509885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
211609885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i));
211709885543Smrg    }
211809885543Smrg
211909885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nVPR    x0       x4       x8       xC");
212009885543Smrg    for (i = 0x00; i <= 0x60; i += 4) {
212109885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
212209885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i));
212309885543Smrg    }
212409885543Smrg
212509885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\nCPR    x0       x4       x8       xC");
212609885543Smrg    for (i = 0x00; i <= 0x18; i += 4) {
212709885543Smrg	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
212809885543Smrg	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i));
212909885543Smrg    }
213009885543Smrg
213109885543Smrg    xf86ErrorFVerb(VERBLEV, "\n\n");
213209885543Smrg    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
213309885543Smrg		"END register dump --------------------\n");
213409885543Smrg
21357104f784Smrg    LEAVE();
213609885543Smrg}
2137407d2e45Smacallan
2138407d2e45Smacallanstatic Bool
2139407d2e45SmacallanSMI_driverFunc(ScrnInfoPtr pScrn, xorgDriverFuncOp op,
2140407d2e45Smacallan    pointer ptr)
2141407d2e45Smacallan{
2142407d2e45Smacallan	xorgHWFlags *flag;
2143407d2e45Smacallan
2144407d2e45Smacallan	switch (op) {
2145407d2e45Smacallan	case GET_REQUIRED_HW_INTERFACES:
2146407d2e45Smacallan		flag = (CARD32*)ptr;
2147407d2e45Smacallan		(*flag) = HW_MMIO;
2148407d2e45Smacallan		return TRUE;
2149407d2e45Smacallan	default:
2150407d2e45Smacallan		return FALSE;
2151407d2e45Smacallan	}
2152407d2e45Smacallan}
2153