smi_driver.c revision b698ba48
11.376Spalle/* Header:   //Mercury/Projects/archives/XFree86/4.0/smi_driver.c-arc   1.42   03 Jan 2001 13:52:16   Frido  $ */
21.1Sabs
31.123Sjmc/*
41.123SjmcCopyright (C) 1994-1999 The XFree86 Project, Inc.  All Rights Reserved.
51.123SjmcCopyright (C) 2000 Silicon Motion, Inc.  All Rights Reserved.
61.1Sabs
71.123SjmcPermission is hereby granted, free of charge, to any person obtaining a copy of
81.123Sjmcthis software and associated documentation files (the "Software"), to deal in
91.123Sjmcthe Software without restriction, including without limitation the rights to
101.123Sjmcuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
111.123Sjmcof the Software, and to permit persons to whom the Software is furnished to do
121.123Sjmcso, subject to the following conditions:
131.123Sjmc
141.257SapbThe above copyright notice and this permission notice shall be included in all
151.257Sapbcopies or substantial portions of the Software.
161.257Sapb
171.123SjmcTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
181.1SabsIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
191.1SabsNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
201.1SabsXFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
211.230StlsAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
221.375SchristosWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
231.375Schristos
241.376SpalleExcept as contained in this notice, the names of The XFree86 Project and
251.367SriastradSilicon Motion shall not be used in advertising or otherwise to promote the
261.373Sriastradsale, use or other dealings in this Software without prior written
271.373Sriastradauthorization from The XFree86 Project or Silicon Motion.
281.368Sriastrad*/
291.372Sriastrad
301.370Sriastrad#ifdef HAVE_CONFIG_H
311.372Sriastrad#include "config.h"
321.368Sriastrad#endif
331.374Sriastrad
341.374Sriastrad#include "xf86.h"
351.374Sriastrad#include "xf86DDC.h"
361.374Sriastrad#include "xf86int10.h"
371.374Sriastrad#include "vbe.h"
381.374Sriastrad
391.374Sriastrad#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
401.367Sriastrad#include "xf86Resources.h"
411.367Sriastrad#include "xf86RAC.h"
421.367Sriastrad#endif
431.367Sriastrad
441.367Sriastrad#include "smi.h"
451.367Sriastrad#include "smi_501.h"
461.367Sriastrad#include "smilynx.h"
471.367Sriastrad#include "smi_crtc.h"
481.367Sriastrad
491.363Smartin#include "globals.h"
501.363Smartin#ifdef HAVE_XEXTPROTO_71
511.363Smartin#include <X11/extensions/dpmsconst.h>
521.366Sriastrad#else
531.366Sriastrad#define DPMS_SERVER
541.366Sriastrad#include <X11/extensions/dpms.h>
551.366Sriastrad#endif
561.366Sriastrad
571.366Sriastrad
581.366Sriastrad/*
591.366Sriastrad * Internals
601.366Sriastrad */
611.366Sriastradstatic Bool SMI_MapMmio(ScrnInfoPtr pScrn);
621.366Sriastradstatic Bool SMI_DetectMem(ScrnInfoPtr pScrn);
631.366Sriastradstatic void SMI_EnableMmio(ScrnInfoPtr pScrn);
641.366Sriastradstatic void SMI_DisableMmio(ScrnInfoPtr pScrn);
651.366Sriastradstatic Bool SMI_HWInit(ScrnInfoPtr pScrn);
661.366Sriastrad
671.363Smartin/*
681.360Swiz * Forward definitions for the functions that make up the driver.
691.360Swiz */
701.360Swiz
711.360Swizstatic const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid);
721.360Swizstatic void SMI_Identify(int flags);
731.360Swizstatic Bool SMI_Probe(DriverPtr drv, int flags);
741.360Swizstatic Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
751.358Smartinstatic Bool SMI_EnterVT(int scrnIndex, int flags);
761.358Smartinstatic void SMI_LeaveVT(int scrnIndex, int flags);
771.359Smartinstatic Bool SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc,
781.359Smartin                           char **argv);
791.359Smartinstatic void SMI_DisableVideo(ScrnInfoPtr pScrn);
801.359Smartinstatic void SMI_EnableVideo(ScrnInfoPtr pScrn);
811.359Smartinstatic Bool SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen);
821.358Smartinstatic Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
831.357Schristosstatic void SMI_FreeScreen(int ScrnIndex, int flags);
841.357Schristosstatic void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
851.357Schristosstatic void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
861.357Schristosstatic void SMI_DetectMCLK(ScrnInfoPtr pScrn);
871.358Smartin
881.355Smartin/*
891.355Smartin * xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
901.355Smartin * format "%s(%d): " so, use name "SMI" instead of "Silicon Motion"
911.355Smartin */
921.356Sriastrad#define SILICONMOTION_NAME          "SMI"
931.354Smartin#define SILICONMOTION_DRIVER_NAME   "siliconmotion"
941.353Smartin#define SILICONMOTION_VERSION_NAME  PACKAGE_VERSION
951.353Smartin#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR
961.353Smartin#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR
971.352Skre#define SILICONMOTION_PATCHLEVEL    PACKAGE_VERSION_PATCHLEVEL
981.352Skre#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
991.352Skre                                      (SILICONMOTION_VERSION_MINOR << 16) | \
1001.352Skre                                      (SILICONMOTION_PATCHLEVEL))
1011.352Skre
1021.350Sriastrad#if SMI_DEBUG
1031.350Sriastradint smi_indent = 1;
1041.350Sriastrad#endif
1051.350Sriastrad
1061.349Smaya/* for dualhead */
1071.349Smayaint gSMIEntityIndex = -1;
1081.349Smaya
1091.346Sriastrad/*
1101.346Sriastrad * This contains the functions needed by the server after loading the
1111.346Sriastrad * driver module.  It must be supplied, and gets added the driver list by
1121.346Sriastrad * the Module Setup funtion in the dynamic case.  In the static case a
1131.346Sriastrad * reference to this is compiled in, and this requires that the name of
1141.347Snia * this DriverRec be an upper-case version of the driver name.
1151.347Snia */
1161.347Snia
1171.347Snia_X_EXPORT DriverRec SILICONMOTION =
1181.343Sriastrad{
1191.343Sriastrad    SILICONMOTION_DRIVER_VERSION,
1201.343Sriastrad    SILICONMOTION_DRIVER_NAME,
1211.343Sriastrad    SMI_Identify,
1221.343Sriastrad    SMI_Probe,
1231.343Sriastrad    SMI_AvailableOptions,
1241.343Sriastrad    NULL,
1251.343Sriastrad    0
1261.343Sriastrad};
1271.343Sriastrad
1281.343Sriastrad/* Supported chipsets */
1291.343Sriastradstatic SymTabRec SMIChipsets[] =
1301.343Sriastrad{
1311.343Sriastrad    { PCI_CHIP_SMI910, "Lynx"    },
1321.343Sriastrad    { PCI_CHIP_SMI810, "LynxE"   },
1331.341Slukem    { PCI_CHIP_SMI820, "Lynx3D"  },
1341.341Slukem    { PCI_CHIP_SMI710, "LynxEM"  },
1351.341Slukem    { PCI_CHIP_SMI712, "LynxEM+" },
1361.341Slukem    { PCI_CHIP_SMI720, "Lynx3DM" },
1371.342Smartin    { PCI_CHIP_SMI731, "Cougar3DR" },
1381.342Smartin    { PCI_CHIP_SMI501, "MSOC"	 },
1391.342Smartin    { -1,             NULL      }
1401.342Smartin};
1411.342Smartin
1421.342Smartinstatic PciChipsets SMIPciChipsets[] =
1431.339Smartin{
1441.339Smartin    /* numChipset,	PciID,			Resource */
1451.339Smartin    { PCI_CHIP_SMI910,	PCI_CHIP_SMI910,	RES_SHARED_VGA },
1461.339Smartin    { PCI_CHIP_SMI810,	PCI_CHIP_SMI810,	RES_SHARED_VGA },
1471.339Smartin    { PCI_CHIP_SMI820,	PCI_CHIP_SMI820,	RES_SHARED_VGA },
1481.338Slukem    { PCI_CHIP_SMI710,	PCI_CHIP_SMI710,	RES_SHARED_VGA },
1491.338Slukem    { PCI_CHIP_SMI712,	PCI_CHIP_SMI712,	RES_SHARED_VGA },
1501.338Slukem    { PCI_CHIP_SMI720,	PCI_CHIP_SMI720,	RES_SHARED_VGA },
1511.338Slukem    { PCI_CHIP_SMI731,	PCI_CHIP_SMI731,	RES_SHARED_VGA },
1521.338Slukem    { PCI_CHIP_SMI501,	PCI_CHIP_SMI501,	RES_UNDEFINED  },
1531.340Smartin    { -1,		-1,			RES_UNDEFINED  }
1541.340Smartin};
1551.345Sandvar
1561.340Smartintypedef enum
1571.340Smartin{
1581.340Smartin    OPTION_PCI_BURST,
1591.337Smrg    OPTION_PCI_RETRY,
1601.337Smrg    OPTION_NOACCEL,
1611.337Smrg    OPTION_MCLK,
1621.337Smrg    OPTION_MXCLK,
1631.337Smrg    OPTION_SWCURSOR,
1641.337Smrg    OPTION_HWCURSOR,
1651.336Smartin    OPTION_VIDEOKEY,
1661.336Smartin    OPTION_BYTESWAP,
1671.336Smartin    /* CZ 26.10.2001: interlaced video */
1681.336Smartin    OPTION_INTERLACED,
1691.336Smartin    /* end CZ */
1701.336Smartin    OPTION_USEBIOS,
1711.335Schs    OPTION_DUALHEAD,
1721.335Schs    OPTION_ACCELMETHOD,
1731.335Schs    OPTION_PANEL_SIZE,
1741.335Schs    OPTION_USE_FBDEV,
1751.335Schs    OPTION_CSCVIDEO,
1761.335Schs    NUMBER_OF_OPTIONS
1771.335Schs} SMIOpts;
1781.335Schs
1791.335Schsstatic const OptionInfoRec SMIOptions[] =
1801.335Schs{
1811.335Schs    { OPTION_PCI_BURST,	     "pci_burst",	  OPTV_BOOLEAN, {0}, TRUE },
1821.335Schs    { OPTION_PCI_RETRY,	     "pci_retry",	  OPTV_BOOLEAN, {0}, TRUE },
1831.335Schs    { OPTION_NOACCEL,	     "NoAccel",		  OPTV_BOOLEAN, {0}, FALSE },
1841.335Schs    { OPTION_MCLK,	     "MCLK",		  OPTV_FREQ,	{0}, FALSE },
1851.335Schs    { OPTION_MXCLK,	     "MXCLK",		  OPTV_FREQ,	{0}, FALSE },
1861.335Schs    { OPTION_HWCURSOR,	     "HWCursor",	  OPTV_BOOLEAN, {0}, TRUE },
1871.335Schs    { OPTION_SWCURSOR,	     "SWCursor",	  OPTV_BOOLEAN, {0}, FALSE },
1881.335Schs    { OPTION_VIDEOKEY,	     "VideoKey",	  OPTV_INTEGER, {0}, FALSE },
1891.335Schs    { OPTION_BYTESWAP,	     "ByteSwap",	  OPTV_BOOLEAN, {0}, FALSE },
1901.335Schs    /* CZ 26.10.2001: interlaced video */
1911.335Schs    { OPTION_INTERLACED,     "Interlaced",        OPTV_BOOLEAN, {0}, FALSE },
1921.335Schs    /* end CZ */
1931.335Schs    { OPTION_USEBIOS,	     "UseBIOS",		  OPTV_BOOLEAN,	{0}, FALSE },
1941.335Schs    { OPTION_DUALHEAD,	     "Dualhead",	  OPTV_BOOLEAN,	{0}, TRUE },
1951.335Schs    { OPTION_ACCELMETHOD,    "AccelMethod",       OPTV_STRING,  {0}, FALSE },
1961.335Schs    { OPTION_PANEL_SIZE,     "PanelSize",	  OPTV_ANYSTR,	{0}, FALSE },
1971.334Smrg    { OPTION_USE_FBDEV,	     "UseFBDev",	  OPTV_BOOLEAN,	{0}, FALSE },
1981.334Smrg    { OPTION_CSCVIDEO,	     "CSCVideo",	  OPTV_BOOLEAN, {0}, TRUE },
1991.334Smrg    { -1,		     NULL,		  OPTV_NONE,	{0}, FALSE }
2001.334Smrg};
2011.334Smrg
2021.334Smrg#ifdef XFree86LOADER
2031.334Smrg
2041.334Smrgstatic MODULESETUPPROTO(siliconmotionSetup);
2051.334Smrg
2061.334Smrgstatic XF86ModuleVersionInfo SMIVersRec =
2071.334Smrg{
2081.331Sriastrad    "siliconmotion",
2091.331Sriastrad    MODULEVENDORSTRING,
2101.333Sriastrad    MODINFOSTRING1,
2111.333Sriastrad    MODINFOSTRING2,
2121.333Sriastrad    XORG_VERSION_CURRENT,
2131.333Sriastrad    SILICONMOTION_VERSION_MAJOR,
2141.333Sriastrad    SILICONMOTION_VERSION_MINOR,
2151.333Sriastrad    SILICONMOTION_PATCHLEVEL,
2161.333Sriastrad    ABI_CLASS_VIDEODRV,
2171.333Sriastrad    ABI_VIDEODRV_VERSION,
2181.333Sriastrad    MOD_CLASS_VIDEODRV,
2191.333Sriastrad    {0, 0, 0, 0}
2201.333Sriastrad};
2211.333Sriastrad
2221.333Sriastrad/*
2231.333Sriastrad * This is the module init data for XFree86 modules.
2241.333Sriastrad *
2251.333Sriastrad * Its name has to be the driver name followed by ModuleData.
2261.333Sriastrad */
2271.333Sriastrad_X_EXPORT XF86ModuleData siliconmotionModuleData =
2281.333Sriastrad{
2291.333Sriastrad    &SMIVersRec,
2301.333Sriastrad    siliconmotionSetup,
2311.333Sriastrad    NULL
2321.333Sriastrad};
2331.333Sriastrad
2341.333Sriastradstatic pointer
2351.333SriastradsiliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin)
2361.331Sriastrad{
2371.330Slukem    static Bool setupDone = FALSE;
2381.330Slukem
2391.330Slukem    if (!setupDone) {
2401.330Slukem	setupDone = TRUE;
2411.329Smrg	xf86AddDriver(&SILICONMOTION, module, 0);
2421.329Smrg
2431.329Smrg	/*
2441.329Smrg	 * The return value must be non-NULL on success even though there
2451.328Smartin	 * is no TearDownProc.
2461.328Smartin	 */
2471.328Smartin	return (pointer) 1;
2481.328Smartin
2491.324Smartin    } else {
2501.324Smartin	if (errmaj) {
2511.325Smartin	    *errmaj = LDR_ONCEONLY;
2521.324Smartin	}
2531.323Snia	return NULL;
2541.323Snia    }
2551.323Snia}
2561.323Snia
2571.322Smartin#endif /* XFree86LOADER */
2581.323Snia
2591.322Smartinstatic Bool
2601.321SchristosSMI_GetRec(ScrnInfoPtr pScrn)
2611.321Schristos{
2621.321Schristos    ENTER();
2631.321Schristos
2641.321Schristos    /*
2651.319Smrg     * Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
2661.319Smrg     * pScrn->driverPrivate is initialised to NULL, so we can check if
2671.319Smrg     * the allocation has already been done.
2681.319Smrg     */
2691.318Smrg    if (pScrn->driverPrivate == NULL) {
2701.318Smrg	pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
2711.351Sgutterid    }
2721.318Smrg
2731.318Smrg    LEAVE(TRUE);
2741.316Smrg}
2751.316Smrg
2761.316Smrgstatic void
2771.316SmrgSMI_FreeRec(ScrnInfoPtr pScrn)
2781.315Smrg{
2791.315Smrg    SMIPtr	pSmi = SMIPTR(pScrn);
2801.315Smrg
2811.315Smrg    ENTER();
2821.314Smrg
2831.314Smrg    if (pSmi) {
2841.314Smrg	xfree(pSmi->save);
2851.314Smrg	xfree(pSmi->mode);
2861.313Smrg	xfree(pScrn->driverPrivate);
2871.313Smrg	pScrn->driverPrivate = NULL;
2881.313Smrg    }
2891.313Smrg
2901.311Smrg    LEAVE();
2911.312Smrg}
2921.312Smrg
2931.312Smrgstatic const OptionInfoRec *
2941.311SmrgSMI_AvailableOptions(int chipid, int busid)
2951.309Schristos{
2961.310Schristos    ENTER();
2971.332Sgutterid
2981.309Schristos    LEAVE(SMIOptions);
2991.308Schristos}
3001.308Schristos
3011.308Schristosstatic void
3021.308SchristosSMI_Identify(int flags)
3031.307Smrg{
3041.307Smrg    ENTER();
3051.307Smrg
3061.307Smrg    xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
3071.306Schristos		SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
3081.306Schristos		SMIChipsets);
3091.306Schristos
3101.306Schristos    LEAVE();
3111.306Schristos}
3121.305Smartin
3131.305Smartinstatic Bool
3141.305SmartinSMI_Probe(DriverPtr drv, int flags)
3151.305Smartin{
3161.304Smartin    int i;
3171.304Smartin    GDevPtr *devSections;
3181.304Smartin    int *usedChips;
3191.304Smartin    int numDevSections;
3201.304Smartin    int numUsed;
3211.306Schristos    Bool foundScreen = FALSE;
3221.304Smartin
3231.304Smartin    ENTER();
3241.303Smrg
3251.303Smrg    numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
3261.303Smrg
3271.303Smrg    if (numDevSections <= 0)
3281.303Smrg	/* There's no matching device section in the config file, so quit now. */
3291.302Sriastrad	LEAVE(FALSE);
3301.306Schristos
3311.302Sriastrad#ifndef XSERVER_LIBPCIACCESS
3321.302Sriastrad    if (xf86GetPciVideoInfo() == NULL)
3331.302Sriastrad	LEAVE(FALSE);
3341.302Sriastrad#endif
3351.302Sriastrad
3361.302Sriastrad    numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
3371.302Sriastrad				    SMIChipsets, SMIPciChipsets, devSections,
3381.302Sriastrad				    numDevSections, drv, &usedChips);
3391.302Sriastrad
3401.302Sriastrad    /* Free it since we don't need that list after this */
3411.302Sriastrad    xfree(devSections);
3421.302Sriastrad    if (numUsed <= 0)
3431.302Sriastrad	LEAVE(FALSE);
3441.302Sriastrad
3451.302Sriastrad    if (flags & PROBE_DETECT)
3461.302Sriastrad	foundScreen = TRUE;
3471.302Sriastrad    else {
3481.302Sriastrad	ScrnInfoPtr	pScrn;
3491.302Sriastrad	EntityInfoPtr	pEnt;
3501.302Sriastrad
3511.302Sriastrad	for (i = 0; i < numUsed; i++) {
3521.302Sriastrad	    if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
3531.302Sriastrad					     SMIPciChipsets, NULL,
3541.302Sriastrad					     NULL, NULL, NULL, NULL))) {
3551.302Sriastrad		pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
3561.302Sriastrad		pScrn->driverName    = SILICONMOTION_DRIVER_NAME;
3571.302Sriastrad		pScrn->name	     = SILICONMOTION_NAME;
3581.302Sriastrad		pScrn->Probe	     = SMI_Probe;
3591.302Sriastrad		pScrn->PreInit	     = SMI_PreInit;
3601.302Sriastrad		pScrn->ScreenInit    = SMI_ScreenInit;
3611.302Sriastrad		pScrn->SwitchMode    = SMI_SwitchMode;
3621.302Sriastrad		pScrn->AdjustFrame   = SMI_AdjustFrame;
3631.302Sriastrad
3641.302Sriastrad		if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
3651.302Sriastrad			pScrn->EnterVT   = SMI_EnterVT;
3661.302Sriastrad			pScrn->LeaveVT   = SMI_LeaveVT;
3671.302Sriastrad		    xfree(pEnt);
3681.302Sriastrad		}
3691.302Sriastrad		pScrn->FreeScreen    = SMI_FreeScreen;
3701.302Sriastrad		foundScreen	     = TRUE;
3711.302Sriastrad	    }
3721.302Sriastrad	}
3731.302Sriastrad    }
3741.302Sriastrad    xfree(usedChips);
3751.302Sriastrad
3761.302Sriastrad    LEAVE(foundScreen);
3771.302Sriastrad}
3781.302Sriastrad
3791.302Sriastradstatic Bool
3801.302SriastradSMI_PreInit(ScrnInfoPtr pScrn, int flags)
3811.302Sriastrad{
3821.302Sriastrad    EntityInfoPtr pEnt;
3831.302Sriastrad    SMIPtr pSmi;
3841.302Sriastrad    MessageType from;
3851.302Sriastrad    vgaHWPtr hwp;
3861.302Sriastrad
3871.302Sriastrad    ENTER();
3881.302Sriastrad
3891.302Sriastrad    /* Ignoring the Type list for now.  It might be needed when multiple cards
3901.302Sriastrad     * are supported.
3911.302Sriastrad     */
3921.302Sriastrad    if (pScrn->numEntities > 1)
3931.302Sriastrad	LEAVE(FALSE);
3941.302Sriastrad
3951.302Sriastrad    /* Allocate the SMIRec driverPrivate */
3961.302Sriastrad    if (!SMI_GetRec(pScrn))
3971.302Sriastrad	LEAVE(FALSE);
3981.302Sriastrad    pSmi = SMIPTR(pScrn);
3991.302Sriastrad
4001.302Sriastrad    /* Find the PCI slot for this screen */
4011.302Sriastrad    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
4021.302Sriastrad
4031.302Sriastrad    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
4041.302Sriastrad    pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
4051.302Sriastrad
4061.302Sriastrad    if (IS_MSOC(pSmi)) {
4071.302Sriastrad	pSmi->Save = SMI501_Save;
4081.302Sriastrad	pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
4091.301Smartin	pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
4101.301Smartin    }
4111.301Smartin    else {
4121.301Smartin	pSmi->Save = SMILynx_Save;
4131.301Smartin	pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
4141.301Smartin	pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
4151.300Smartin    }
4161.344Sgutterid
4171.300Smartin    if (flags & PROBE_DETECT) {
4181.326Sandvar	if (!IS_MSOC(pSmi))
4191.300Smartin	    SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
4201.300Smartin	LEAVE(TRUE);
4211.300Smartin    }
4221.299Smrg
4231.299Smrg    if (pEnt->location.type != BUS_PCI) {
4241.299Smrg	xfree(pEnt);
4251.1Sabs	SMI_FreeRec(pScrn);
4261.1Sabs	LEAVE(FALSE);
4271.123Sjmc    }
4281.132Sjmmv    pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
4291.123Sjmc
4301.123Sjmc    /* Set pScrn->monitor */
4311.123Sjmc    pScrn->monitor = pScrn->confScreen->monitor;
4321.123Sjmc
4331.2Smrg    if (!IS_MSOC(pSmi)) {
4341.2Smrg	/* The vgahw module should be loaded here when needed */
4351.2Smrg	if (!xf86LoadSubModule(pScrn, "vgahw"))
4361.2Smrg	    LEAVE(FALSE);
4371.1Sabs
4381.1Sabs	/*
4391.1Sabs	 * Allocate a vgaHWRec
4401.1Sabs	 */
4411.1Sabs	if (!vgaHWGetHWRec(pScrn))
4421.1Sabs	    LEAVE(FALSE);
4431.123Sjmc
4441.123Sjmc	hwp = VGAHWPTR(pScrn);
4451.123Sjmc	pSmi->PIOBase = hwp->PIOOffset;
4461.1Sabs
4471.2Smrg	xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
4481.2Smrg		       "MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET,
4491.1Sabs		       hwp->IOBase, hwp->MMIOBase);
4501.2Smrg    }
4511.2Smrg
4521.1Sabs    /*
4531.123Sjmc     * The first thing we should figure out is the depth, bpp, etc.
4541.123Sjmc     */
4551.123Sjmc    if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
4561.123Sjmc	LEAVE(FALSE);
4571.123Sjmc
4581.123Sjmc    /* Check that the returned depth is one we support */
4591.123Sjmc    if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) {
4601.123Sjmc	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4611.123Sjmc		   "Given depth (%d) is not supported by this driver\n",
4621.123Sjmc		   pScrn->depth);
4631.1Sabs	LEAVE(FALSE);
4641.1Sabs    }
4651.1Sabs
4661.123Sjmc
4671.123Sjmc    if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
4681.241Swiz       pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
4691.1Sabs	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
4701.1Sabs		   "Given bpp (%d) is not supported by this driver\n",
4711.230Stls		   pScrn->bitsPerPixel);
4721.1Sabs	LEAVE(FALSE);
4731.1Sabs    }
4741.1Sabs
4751.1Sabs    xf86PrintDepthBpp(pScrn);
4761.1Sabs
4771.1Sabs    pSmi->Bpp = pScrn->bitsPerPixel >> 3;
4781.1Sabs
4791.1Sabs    /*
4801.1Sabs     * This must happen after pScrn->display has been set because
4811.1Sabs     * xf86SetWeight references it.
4821.1Sabs     */
4831.1Sabs    if (pScrn->depth > 8) {
4841.1Sabs	/* The defaults are OK for us */
4851.1Sabs	rgb zeros = {0, 0, 0};
4861.1Sabs#if __BYTE_ORDER == __BIG_ENDIAN
4871.1Sabs	rgb masks = {0xff00,0xff0000,0xff000000};
4881.1Sabs#else
4891.1Sabs	rgb masks = {0, 0, 0};
4901.1Sabs#endif
4911.1Sabs
4921.1Sabs	if (!xf86SetWeight(pScrn, zeros, masks))
4931.1Sabs	    LEAVE(FALSE);
4941.1Sabs    }
4951.2Smrg
4961.2Smrg    if (!xf86SetDefaultVisual(pScrn, -1))
4971.2Smrg	LEAVE(FALSE);
4981.1Sabs
4991.1Sabs    /* We don't currently support DirectColor at > 8bpp */
5001.1Sabs    if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
5011.1Sabs	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) "
5021.1Sabs		   "is not supported at depth %d\n",
5031.58Slukem		   xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
5041.58Slukem	LEAVE(FALSE);
5051.1Sabs    }
5061.58Slukem
5071.1Sabs    /* We use a programmable clock */
5081.1Sabs    pScrn->progClock = TRUE;
5091.1Sabs
5101.58Slukem    /* Collect all of the relevant option flags (fill in pScrn->options) */
5111.1Sabs    xf86CollectOptions(pScrn, NULL);
5121.1Sabs
5131.1Sabs    /* Set the bits per RGB for 8bpp mode */
5141.1Sabs    if (pScrn->depth == 8){
5151.1Sabs	pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
5161.1Sabs    }else if(pScrn->depth == 16){
5171.1Sabs	/* Use 8 bit LUT for gamma correction*/
5181.1Sabs	pScrn->rgbBits = 8;
5191.58Slukem    }
5201.1Sabs
5211.1Sabs    /* Process the options */
5221.1Sabs    if (!(pSmi->Options = xalloc(sizeof(SMIOptions))))
5231.1Sabs	LEAVE(FALSE);
5241.1Sabs
5251.1Sabs    memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
5261.1Sabs    xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
5271.1Sabs
5281.11Slukem    /* Enable pci burst by default */
5291.142Sdrochner    from = X_DEFAULT;
5301.1Sabs    pSmi->PCIBurst = TRUE;
5311.34Ssimonb    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst))
5321.1Sabs	from = X_CONFIG;
5331.1Sabs    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n",
5341.17Serh	       pSmi->PCIBurst ? "en" : "dis");
5351.17Serh
5361.111Ssimonb    /* Pci retry enabled by default if pci burst also enabled */
5371.348Srillig    from = X_DEFAULT;
5381.348Srillig    pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE;
5391.17Serh    if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) {
5401.1Sabs	from = X_CONFIG;
5411.1Sabs	if (pSmi->PCIRetry && !pSmi->PCIBurst) {
5421.2Smrg	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
5431.2Smrg		       "\"pci_retry\" option requires \"pci_burst\".\n");
5441.142Sdrochner	    pSmi->PCIRetry = FALSE;
5451.1Sabs	}
5461.4Sitojun    }
5471.4Sitojun    xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n",
5481.4Sitojun	       pSmi->PCIRetry ? "en" : "dis");
5491.4Sitojun
5501.4Sitojun    if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) {
5511.5Swiz	pSmi->NoAccel = TRUE;
5521.207Smbalmer	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
5531.207Smbalmer		   "disabled\n");
5541.5Swiz    } else {
5551.12Sitojun	pSmi->NoAccel = FALSE;
5561.12Sitojun    }
5571.12Sitojun
5581.13Sdogcow    if (IS_MSOC(pSmi)) {
5591.86Skleink	from = X_DEFAULT;
5601.13Sdogcow	if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
5611.13Sdogcow	    from = X_CONFIG;
5621.142Sdrochner	xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n",
5631.19Scgd		   pSmi->UseFBDev ? "enabled" : "disabled");
5641.13Sdogcow    }
5651.19Scgd
5661.19Scgd    from = X_CONFIG;
5671.24Sabs    pSmi->HwCursor = TRUE;
5681.223Sjoerg    /* SWCursor overrides HWCusor if both specified */
5691.223Sjoerg    if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
5701.223Sjoerg	pSmi->HwCursor = FALSE;
5711.257Sapb    else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
5721.257Sapb	from = X_DEFAULT;
5731.257Sapb
5741.257Sapb    xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
5751.257Sapb	       pSmi->HwCursor ? "Hard" : "Soft");
5761.257Sapb
5771.257Sapb    if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
5781.257Sapb	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
5791.257Sapb		   "0x%08X\n", pSmi->videoKey);
5801.257Sapb    } else {
581	pSmi->videoKey = (1 << pScrn->offset.red) |
582			 (1 << pScrn->offset.green) |
583			 (((pScrn->mask.blue >> pScrn->offset.blue) - 1)
584			 << pScrn->offset.blue);
585    }
586
587    if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) {
588	pSmi->ByteSwap = TRUE;
589	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
590    } else {
591	pSmi->ByteSwap = FALSE;
592    }
593
594    /* CZ 26.10.2001: interlaced video */
595    if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) {
596	pSmi->interlaced = TRUE;
597	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
598    } else {
599	pSmi->interlaced = FALSE;
600    }
601    /* end CZ */
602
603    if (IS_MSOC(pSmi))
604	pSmi->useBIOS = FALSE;
605    else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) {
606	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
607		   pSmi->useBIOS ? "enabled" : "disabled");
608    }
609    else if(pSmi->Chipset == SMI_LYNX3DM){
610	/* Default to UseBIOS disabled. */
611	pSmi->useBIOS = FALSE;
612    }
613    else {
614	/* Default to UseBIOS enabled. */
615	pSmi->useBIOS = TRUE;
616    }
617
618    if (pSmi->useBIOS) {
619	if (xf86LoadSubModule(pScrn,"int10")) {
620	    pSmi->pInt10 = xf86InitInt10(pEnt->index);
621	}
622
623	if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
624	    pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
625	}
626
627	if(!pSmi->pVbe){
628	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n");
629	    pSmi->useBIOS = FALSE;
630	}
631    }
632
633#ifndef XSERVER_LIBPCIACCESS
634    xf86RegisterResources(pEnt->index, NULL, ResExclusive);
635#endif
636    /*
637     * Set the Chipset and ChipRev, allowing config file entries to
638     * override.
639     */
640    if (pEnt->device->chipset && *pEnt->device->chipset) {
641	pScrn->chipset = pEnt->device->chipset;
642	pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
643	from = X_CONFIG;
644    }
645    else if (pEnt->device->chipID >= 0) {
646	pSmi->Chipset = pEnt->device->chipID;
647	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
648	from = X_CONFIG;
649	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
650		   pSmi->Chipset);
651    }
652    else {
653	from = X_PROBED;
654	pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
655	pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
656    }
657
658    if (pEnt->device->chipRev >= 0) {
659	pSmi->ChipRev = pEnt->device->chipRev;
660	xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
661		   pSmi->ChipRev);
662    }
663    else
664        pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo);
665    xfree(pEnt);
666
667    /*
668     * This shouldn't happen because such problems should be caught in
669     * SMI_Probe(), but check it just in case.
670     */
671    if (pScrn->chipset == NULL) {
672	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
673				"recognised\n", pSmi->Chipset);
674	LEAVE(FALSE);
675    }
676
677    if (pSmi->Chipset < 0) {
678	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
679		   "recognised\n", pScrn->chipset);
680	LEAVE(FALSE);
681    }
682
683    xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
684
685#ifndef XSERVER_LIBPCIACCESS
686    pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
687		   	  pSmi->PciInfo->func);
688#endif
689
690    from = X_DEFAULT;
691    if(pSmi->Chipset == SMI_LYNX3DM &&
692       pScrn->bitsPerPixel == 16)
693	pSmi->Dualhead = TRUE;
694    else
695	pSmi->Dualhead = FALSE;
696
697    if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead))
698	from = X_CONFIG;
699
700    if (IS_MSOC(pSmi)) {
701	pSmi->lcd = TRUE;
702	if (pSmi->Dualhead && pSmi->UseFBDev) {
703	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
704		       "Dual head disabled in fbdev mode\n");
705	    pSmi->Dualhead = FALSE;
706	}
707	/* FIXME Randr cursor code only works properly when argb cursors
708	 * are also supported.
709	 * FIXME This probably is a randr cursor bug, and since access to
710	 * hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor
711	 * field is not available, one cannot easily workaround the problem,
712	 * so, just disable it...
713	 * TODO Check with a X Server newer then 1.4.0.90 (that is being
714	 * used in the 502 OEM image).
715	 * */
716	if (pSmi->Dualhead && pSmi->HwCursor) {
717	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
718		       "HW Cursor disabled in dual head mode\n");
719	    pSmi->HwCursor = FALSE;
720	}
721    }
722    else if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
723	/* tweak options for dualhead */
724	if (pSmi->Dualhead) {
725	    pSmi->useBIOS = FALSE;
726	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n");
727	    pSmi->HwCursor = FALSE;
728	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n");
729	    if (pScrn->bitsPerPixel != 16) {
730		xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at "
731			   "depth 16\n");
732		LEAVE(FALSE);
733	    }
734	}
735    }
736    xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n",
737	       pSmi->Dualhead ? "en" : "dis");
738
739    if (!pSmi->NoAccel) {
740	char *strptr;
741
742	from = X_DEFAULT;
743	if ((strptr = (char *)xf86GetOptValString(pSmi->Options,
744						  OPTION_ACCELMETHOD))) {
745	    if (!xf86NameCmp(strptr,"XAA")) {
746		from = X_CONFIG;
747		pSmi->useEXA = FALSE;
748	    } else if(!xf86NameCmp(strptr,"EXA")) {
749		from = X_CONFIG;
750		pSmi->useEXA = TRUE;
751	    }
752	}
753
754	xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
755		pSmi->useEXA ? "EXA" : "XAA");
756    }
757
758    if (IS_MSOC(pSmi)) {
759	pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead;
760	from = X_DEFAULT;
761	if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) {
762	    from = X_CONFIG;
763
764	    /* FIXME */
765	    if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) {
766		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
767			   "CSCVideo requires XAA or EXA in single head mode.\n");
768		pSmi->CSCVideo = FALSE;
769	    }
770	}
771
772	xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n",
773		   pSmi->CSCVideo ? "en" : "dis");
774    }
775
776    SMI_MapMmio(pScrn);
777    SMI_DetectMem(pScrn);
778    SMI_MapMem(pScrn);
779    SMI_DisableVideo(pScrn);
780
781    /* detect the panel size */
782    SMI_DetectPanelSize(pScrn);
783
784    if(!IS_MSOC(pSmi)){
785	if (xf86LoadSubModule(pScrn, "i2c")) {
786	    SMI_I2CInit(pScrn);
787	}
788	xf86LoadSubModule(pScrn, "ddc");
789    }
790
791    /*
792     * If the driver can do gamma correction, it should call xf86SetGamma()
793     */
794    {
795	Gamma zeros = { 0.0, 0.0, 0.0 };
796
797	if (!xf86SetGamma(pScrn, zeros)) {
798	    SMI_EnableVideo(pScrn);
799	    SMI_UnmapMem(pScrn);
800	    LEAVE(FALSE);
801	}
802    }
803
804    SMI_DetectMCLK(pScrn);
805
806    /*
807     * Setup the ClockRanges, which describe what clock ranges are available,
808     * and what sort of modes they can be used for.
809     */
810    pSmi->clockRange.next = NULL;
811    pSmi->clockRange.minClock = 20000;
812
813    if (SMI_LYNXM_SERIES(pSmi->Chipset) ||
814	IS_MSOC(pSmi))
815	pSmi->clockRange.maxClock = 200000;
816    else
817        pSmi->clockRange.maxClock = 135000;
818
819    pSmi->clockRange.clockIndex = -1;
820    pSmi->clockRange.interlaceAllowed = FALSE;
821    pSmi->clockRange.doubleScanAllowed = FALSE;
822
823    if(!SMI_CrtcPreInit(pScrn))
824	LEAVE(FALSE);
825
826    if(!SMI_OutputPreInit(pScrn))
827	LEAVE(FALSE);
828
829    /* Only allow growing the screen dimensions if EXA is being used */
830    if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){
831	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
832
833	SMI_EnableVideo(pScrn);
834	SMI_UnmapMem(pScrn);
835	LEAVE(FALSE);
836    }
837
838    /* Ensure that the framebuffer size just set fits in video memory. */
839    {
840	int aligned_pitch = (pScrn->virtualX*pSmi->Bpp + 15) & ~15;
841
842	if(aligned_pitch * pScrn->virtualY > pSmi->FBReserved){
843	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video memory "
844		       "for the configured screen size (%dx%d) and color depth.\n",
845                       pScrn->virtualX, pScrn->virtualY);
846
847	    SMI_EnableVideo(pScrn);
848	    SMI_UnmapMem(pScrn);
849	    LEAVE(FALSE);
850	}
851    }
852
853
854    SMI_EnableVideo(pScrn);
855    SMI_UnmapMem(pScrn);
856
857    if(pSmi->pVbe){
858       vbeFree(pSmi->pVbe);
859       pSmi->pVbe = NULL;
860    }
861    if(pSmi->pInt10){
862       xf86FreeInt10(pSmi->pInt10);
863       pSmi->pInt10 = NULL;
864    }
865
866    /* Set display resolution */
867    xf86SetDpi(pScrn, 0, 0);
868
869    if (xf86LoadSubModule(pScrn, "fb") == NULL) {
870	SMI_FreeRec(pScrn);
871	LEAVE(FALSE);
872    }
873
874    /* Load XAA or EXA if needed */
875    if (!pSmi->NoAccel) {
876	if (!pSmi->useEXA) {
877	    if (!xf86LoadSubModule(pScrn, "xaa")) {
878		SMI_FreeRec(pScrn);
879		LEAVE(FALSE);
880	    }
881	} else {
882	    XF86ModReqInfo req;
883	    int errmaj, errmin;
884
885	    memset(&req, 0, sizeof(XF86ModReqInfo));
886	    req.majorversion = 2;
887	    req.minorversion = 1;
888
889	    if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
890				&req, &errmaj, &errmin)) {
891		LoaderErrorMsg(NULL, "exa", errmaj, errmin);
892		SMI_FreeRec(pScrn);
893		LEAVE(FALSE);
894	    }
895	}
896    }
897
898    /* Load ramdac if needed */
899    if (pSmi->HwCursor) {
900	if (!xf86LoadSubModule(pScrn, "ramdac")) {
901	    SMI_FreeRec(pScrn);
902	    LEAVE(FALSE);
903	}
904    }
905
906    LEAVE(TRUE);
907}
908
909/*
910 * This is called when VT switching back to the X server.  Its job is to
911 * reinitialise the video mode. We may wish to unmap video/MMIO memory too.
912 */
913
914static Bool
915SMI_EnterVT(int scrnIndex, int flags)
916{
917    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
918    SMIPtr pSmi = SMIPTR(pScrn);
919
920    ENTER();
921
922    /* Enable MMIO and map memory */
923    SMI_MapMem(pScrn);
924
925    pSmi->Save(pScrn);
926
927    /* FBBase may have changed after remapping the memory */
928    pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
929				       -1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
930    pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
931
932    if(pSmi->useEXA)
933       pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
934
935    /* Do the CRTC independent initialization */
936    if(!SMI_HWInit(pScrn))
937	LEAVE(FALSE);
938
939    /* Initialize the chosen modes */
940    if (!xf86SetDesiredModes(pScrn))
941	LEAVE(FALSE);
942
943    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
944		   "Done writing mode.  Register dump:\n");
945    SMI_PrintRegs(pScrn);
946
947    /* Reset the grapics engine */
948    if (!pSmi->NoAccel)
949	SMI_EngineReset(pScrn);
950
951    LEAVE(TRUE);
952}
953
954/*
955 * This is called when VT switching away from the X server.  Its job is to
956 * restore the previous (text) mode. We may wish to remap video/MMIO memory
957 * too.
958 */
959
960static void
961SMI_LeaveVT(int scrnIndex, int flags)
962{
963    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
964    SMIPtr	pSmi = SMIPTR(pScrn);
965
966    ENTER();
967
968    SMI_AccelSync(pScrn);
969
970    /* Ensure that the rotation BlockHandler is unwrapped, and the shadow
971       pixmaps are deallocated, as the video memory is going to be
972       unmapped.  */
973    xf86RotateCloseScreen(pScrn->pScreen);
974
975    /* Pixmaps that by chance get allocated near the former aperture
976       address shouldn't be considered offscreen. */
977    if(pSmi->useEXA)
978       pSmi->EXADriverPtr->memoryBase=NULL;
979
980    /* Clear frame buffer */
981    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
982
983    if (!IS_MSOC(pSmi)) {
984	vgaHWPtr	hwp = VGAHWPTR(pScrn);
985
986	SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
987    }
988    else
989	SMI501_WriteMode(pScrn, pSmi->save);
990
991    SMI_UnmapMem(pScrn);
992
993    LEAVE();
994}
995
996static void
997SMI_DetectPanelSize(ScrnInfoPtr pScrn)
998{
999    char	*s;
1000    int		 width, height;
1001    SMIPtr	 pSmi = SMIPTR(pScrn);
1002
1003    pSmi->lcdWidth  = 0;
1004    pSmi->lcdHeight = 0;
1005    if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) {
1006	if (sscanf(s, "%dx%d", &width, &height) != 2)
1007	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1008		       "Invalid PanelSize option: %s\n", s);
1009	else {
1010	    pSmi->lcdWidth  = width;
1011	    pSmi->lcdHeight = height;
1012	}
1013    }
1014
1015    if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) {
1016	/* panel size detection ... requires BIOS call on 730 hardware */
1017	if (pSmi->Chipset == SMI_COUGAR3DR) {
1018	    if (pSmi->pInt10 != NULL) {
1019		pSmi->pInt10->num = 0x10;
1020		pSmi->pInt10->ax  = 0x5F00;
1021		pSmi->pInt10->bx  = 0;
1022		pSmi->pInt10->cx  = 0;
1023		pSmi->pInt10->dx  = 0;
1024		xf86ExecX86int10(pSmi->pInt10);
1025		if (pSmi->pInt10->ax == 0x005F) {
1026		    switch (pSmi->pInt10->cx & 0x0F) {
1027			case PANEL_640x480:
1028			    pSmi->lcdWidth  = 640;
1029			    pSmi->lcdHeight = 480;
1030			    break;
1031			case PANEL_800x600:
1032			    pSmi->lcdWidth  = 800;
1033			    pSmi->lcdHeight = 600;
1034			    break;
1035			case PANEL_1024x768:
1036			    pSmi->lcdWidth  = 1024;
1037			    pSmi->lcdHeight = 768;
1038			    break;
1039			case PANEL_1280x1024:
1040			    pSmi->lcdWidth  = 1280;
1041			    pSmi->lcdHeight = 1024;
1042			    break;
1043			case PANEL_1600x1200:
1044			    pSmi->lcdWidth  = 1600;
1045			    pSmi->lcdHeight = 1200;
1046			    break;
1047			case PANEL_1400x1050:
1048			    pSmi->lcdWidth  = 1400;
1049			    pSmi->lcdHeight = 1050;
1050			    break;
1051		    }
1052
1053		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1054			       "Detected panel size via BIOS: %d x %d\n",
1055			       pSmi->lcdWidth, pSmi->lcdHeight);
1056		}
1057		else
1058		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1059			       "BIOS error during 730 panel detection!\n");
1060	    }
1061	    else  {
1062		/* int10 support isn't setup on the second call to this function,
1063		  o if this is the second call, don't do detection again */
1064		if (pSmi->lcd == 0)
1065		    /* If we get here, int10 support is not loaded or not working */
1066		    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1067			       "No BIOS support for 730 panel detection!\n");
1068	    }
1069
1070	    /* Set this to indicate that we've done the detection */
1071	    pSmi->lcd = 1;
1072	}
1073	else if (IS_MSOC(pSmi)) {
1074	    pSmi->lcdWidth  = (READ_SCR(pSmi, PANEL_WWIDTH)  >> 16) & 2047;
1075	    pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047;
1076	}
1077	else {
1078	    /* panel size detection for hardware other than 730 */
1079	    pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1080				     0x31) & 0x01;
1081
1082	    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1083			     0x30) & 0x01) {
1084		pSmi->lcd <<= 1;
1085	    }
1086	    switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1087				 0x30) & 0x0C) {
1088		case 0x00:
1089		    pSmi->lcdWidth  = 640;
1090		    pSmi->lcdHeight = 480;
1091		    break;
1092		case 0x04:
1093		    pSmi->lcdWidth  = 800;
1094		    pSmi->lcdHeight = 600;
1095		    break;
1096		case 0x08:
1097		    if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1098				     0x74) & 0x02) {
1099			pSmi->lcdWidth  = 1024;
1100			pSmi->lcdHeight = 600;
1101		    }
1102		    else {
1103			pSmi->lcdWidth  = 1024;
1104			pSmi->lcdHeight = 768;
1105		    }
1106		    break;
1107		case 0x0C:
1108		    pSmi->lcdWidth  = 1280;
1109		    pSmi->lcdHeight = 1024;
1110		    break;
1111	    }
1112	}
1113    }
1114
1115    if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0)
1116	pSmi->lcdWidth = 1024;
1117    if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0)
1118	pSmi->lcdHeight = 768;
1119
1120    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
1121	       (pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
1122	       pSmi->lcdWidth, pSmi->lcdHeight);
1123
1124}
1125
1126static void
1127SMI_DetectMCLK(ScrnInfoPtr pScrn)
1128{
1129    double		real;
1130    MSOCClockRec	clock;
1131    int			mclk, mxclk;
1132    SMIPtr		pSmi = SMIPTR(pScrn);
1133
1134    /* MCLK defaults */
1135    if (pSmi->Chipset == SMI_LYNXEMplus){
1136	/* The SM712 can be safely clocked up to 157MHz, according to
1137	   Silicon Motion engineers. */
1138	pSmi->MCLK = 157000;
1139
1140    } else if (IS_MSOC(pSmi)) {
1141       /* Set some sane defaults for the clock settings if we are on a
1142          SM502 and it's likely to be uninitialized. */
1143
1144       if (!xf86IsPrimaryPci(pSmi->PciInfo) &&
1145           (READ_SCR(pSmi, DEVICE_ID) & 0xFF) >= 0xC0) {
1146          pSmi->MCLK = 112000;
1147          pSmi->MXCLK = 144000;
1148       }
1149
1150    } else {
1151        pSmi->MCLK = 0;
1152        pSmi->MXCLK = 0;
1153    }
1154
1155    /* MCLK from user settings */
1156    if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
1157	if (IS_MSOC(pSmi) || (int)real <= 120) {
1158	    pSmi->MCLK = (int)(real * 1000.0);
1159	} else {
1160	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
1161		       "Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
1162		       real);
1163	}
1164    }
1165    mclk = pSmi->MCLK;
1166
1167    if (IS_MSOC(pSmi)) {
1168	clock.value = READ_SCR(pSmi, CURRENT_CLOCK);
1169	if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK,
1170			      OPTUNITS_MHZ, &real))
1171	    pSmi->MXCLK = (int)(real * 1000.0);
1172    }
1173
1174    /* Already programmed MCLK */
1175    if (pSmi->MCLK == 0) {
1176	if (IS_MSOC(pSmi))
1177	    mclk = ((clock.f.m_select ? 336 : 288) /
1178		    ((clock.f.m_divider ? 3 : 1) <<
1179		     (unsigned)clock.f.m_shift)) * 1000;
1180	else {
1181	    unsigned char	shift, m, n;
1182
1183	    m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
1184	    n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
1185	    switch (n >> 6) {
1186		case 1:
1187		    shift = 4;
1188		    break;
1189		case 2:
1190		    shift = 2;
1191		    break;
1192		default:
1193		    shift = 1;
1194		    break;
1195	    }
1196	    n &= 0x3F;
1197	    mclk = ((1431818 * m) / n / shift + 50) / 100;
1198	}
1199    }
1200
1201    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0);
1202    if (IS_MSOC(pSmi)) {
1203	if (pSmi->MXCLK == 0) {
1204	    mxclk = ((clock.f.m1_select ? 336 : 288) /
1205		     ((clock.f.m1_divider ? 3 : 1) <<
1206		      (unsigned)clock.f.m1_shift)) * 1000;
1207	}
1208	else
1209	    mxclk = pSmi->MXCLK;
1210	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0);
1211    }
1212}
1213
1214static Bool
1215SMI_MapMmio(ScrnInfoPtr pScrn)
1216{
1217    SMIPtr	pSmi = SMIPTR(pScrn);
1218    CARD32	memBase;
1219
1220    SMI_EnableMmio(pScrn);
1221
1222    switch (pSmi->Chipset) {
1223	case SMI_COUGAR3DR:
1224	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
1225	    pSmi->MapSize = 0x200000;
1226	    break;
1227	case SMI_LYNX3D:
1228	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000;
1229	    pSmi->MapSize = 0x180000;
1230	    break;
1231	case SMI_LYNXEM:
1232	case SMI_LYNXEMplus:
1233	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
1234	    pSmi->MapSize = 0x400000;
1235	    break;
1236	case SMI_LYNX3DM:
1237	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
1238	    pSmi->MapSize = 0x200000;
1239	    break;
1240	case SMI_MSOC:
1241	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
1242	    pSmi->MapSize = 0x200000;
1243	    break;
1244	default:
1245	    memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
1246	    pSmi->MapSize = 0x10000;
1247	    break;
1248    }
1249
1250#ifndef XSERVER_LIBPCIACCESS
1251    pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
1252				  memBase, pSmi->MapSize);
1253#else
1254    {
1255	void	**result = (void**)&pSmi->MapBase;
1256	int	  err = pci_device_map_range(pSmi->PciInfo,
1257					     memBase,
1258					     pSmi->MapSize,
1259					     PCI_DEV_MAP_FLAG_WRITABLE,
1260					     result);
1261
1262	if (err)
1263	    return (FALSE);
1264    }
1265#endif
1266
1267    if (pSmi->MapBase == NULL) {
1268	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
1269		   "MMIO registers.\n");
1270	return (FALSE);
1271    }
1272
1273    switch (pSmi->Chipset) {
1274	case SMI_COUGAR3DR:
1275	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
1276	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
1277	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
1278	    pSmi->FPRBase = pSmi->MapBase + 0x005800;
1279	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
1280	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
1281	    pSmi->DataPortSize = 0x100000;
1282	    break;
1283	case SMI_LYNX3D:
1284	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
1285	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
1286	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
1287	    pSmi->IOBase  = pSmi->MapBase + 0x040000;
1288	    pSmi->DataPortBase = pSmi->MapBase + 0x080000;
1289	    pSmi->DataPortSize = 0x100000;
1290	    break;
1291	case SMI_LYNXEM:
1292	case SMI_LYNXEMplus:
1293	    pSmi->DPRBase = pSmi->MapBase + 0x008000;
1294	    pSmi->VPRBase = pSmi->MapBase + 0x00C000;
1295	    pSmi->CPRBase = pSmi->MapBase + 0x00E000;
1296	    pSmi->IOBase  = pSmi->MapBase + 0x300000;
1297	    pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
1298	    pSmi->DataPortSize = 0x8000 /*0x200000*/;
1299	    break;
1300	case SMI_LYNX3DM:
1301	    pSmi->DPRBase = pSmi->MapBase + 0x000000;
1302	    pSmi->VPRBase = pSmi->MapBase + 0x000800;
1303	    pSmi->CPRBase = pSmi->MapBase + 0x001000;
1304	    pSmi->IOBase  = pSmi->MapBase + 0x0C0000;
1305	    pSmi->DataPortBase = pSmi->MapBase + 0x100000;
1306	    pSmi->DataPortSize = 0x100000;
1307	    break;
1308	case SMI_MSOC:
1309	    pSmi->DPRBase = pSmi->MapBase + 0x100000;
1310	    pSmi->VPRBase = pSmi->MapBase + 0x000000;
1311	    pSmi->CPRBase = pSmi->MapBase + 0x090000;
1312	    pSmi->DCRBase = pSmi->MapBase + 0x080000;
1313	    pSmi->SCRBase = pSmi->MapBase + 0x000000;
1314	    pSmi->IOBase = 0;
1315	    pSmi->DataPortBase = pSmi->MapBase + 0x110000;
1316	    pSmi->DataPortSize = 0x10000;
1317	    break;
1318	default:
1319	    pSmi->DPRBase = pSmi->MapBase + 0x8000;
1320	    pSmi->VPRBase = pSmi->MapBase + 0xC000;
1321	    pSmi->CPRBase = pSmi->MapBase + 0xE000;
1322	    pSmi->IOBase  = NULL;
1323	    pSmi->DataPortBase = pSmi->MapBase;
1324	    pSmi->DataPortSize = 0x8000;
1325	    break;
1326    }
1327
1328    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1329		   "Physical MMIO at 0x%08lX\n", (unsigned long)memBase);
1330    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1331		   "Logical MMIO at %p - %p\n", pSmi->MapBase,
1332		   pSmi->MapBase + pSmi->MapSize - 1);
1333    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1334		   "DPR=%p, VPR=%p, IOBase=%p\n",
1335		   pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase);
1336    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1337		   "DataPort=%p - %p\n", pSmi->DataPortBase,
1338		   pSmi->DataPortBase + pSmi->DataPortSize - 1);
1339
1340    return (TRUE);
1341}
1342
1343/* HACK - In some cases the BIOS hasn't filled in the "scratchpad
1344   registers" (SR71) with the right amount of memory installed (e.g. MIPS
1345   platform). Probe it manually. */
1346static unsigned long
1347SMI_ProbeMem(ScrnInfoPtr pScrn, unsigned long mem_skip, unsigned long mem_max)
1348{
1349    SMIPtr pSmi = SMIPTR(pScrn);
1350    unsigned long mem_probe = 1024*1024;
1351    unsigned long aperture_base;
1352    void* mem;
1353
1354    ENTER();
1355
1356    aperture_base = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + mem_skip;
1357    mem_max = min(mem_max , PCI_REGION_SIZE(pSmi->PciInfo, 0) - mem_skip);
1358
1359#ifndef XSERVER_LIBPCIACCESS
1360    mem = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
1361			aperture_base, mem_max);
1362
1363    if(!mem)
1364	LEAVE(0);
1365#else
1366    if(pci_device_map_range(pSmi->PciInfo, aperture_base, mem_max,
1367			    PCI_DEV_MAP_FLAG_WRITABLE, &mem))
1368	LEAVE(0);
1369#endif
1370
1371    while(mem_probe <= mem_max){
1372	MMIO_OUT32(mem, mem_probe-4, 0x55555555);
1373	if(MMIO_IN32(mem, mem_probe-4) != 0x55555555)
1374	    break;
1375
1376	MMIO_OUT32(mem, mem_probe-4, 0xAAAAAAAA);
1377	if(MMIO_IN32(mem, mem_probe-4) != 0xAAAAAAAA)
1378	    break;
1379
1380	mem_probe <<= 1;
1381    }
1382
1383#ifndef XSERVER_LIBPCIACCESS
1384    xf86UnMapVidMem(pScrn->scrnIndex, mem, mem_max);
1385#else
1386    pci_device_unmap_range(pSmi->PciInfo, mem, mem_max);
1387#endif
1388
1389    LEAVE(mem_probe >> 1);
1390}
1391
1392static Bool
1393SMI_DetectMem(ScrnInfoPtr pScrn)
1394{
1395    SMIPtr	pSmi = SMIPTR(pScrn);
1396    MessageType from;
1397
1398    if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){
1399	pSmi->videoRAMKBytes = pScrn->videoRam;
1400	from = X_CONFIG;
1401    }
1402    else {
1403	unsigned char	 config;
1404	static int	 lynx3d_table[4]  = {  0, 2, 4, 6 };
1405	static int	 lynx3dm_table[4] = { 16, 2, 4, 8 };
1406	static int	 msoc_table[8]    = {  4, 8, 16, 32, 64, 2, 0, 0 };
1407	static int	 default_table[4] = {  1, 2, 4, 0 };
1408
1409	if (IS_MSOC(pSmi)) {
1410	    config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7;
1411	    pSmi->videoRAMKBytes = msoc_table[config] * 1024 -
1412		SHARED_USB_DMA_BUFFER_SIZE;
1413	}
1414	else {
1415	    config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
1416	    switch (pSmi->Chipset) {
1417		case SMI_LYNX3D:
1418		    pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 +
1419			512;
1420		    break;
1421		case SMI_LYNXEMplus:
1422		    pSmi->videoRAMKBytes = SMI_ProbeMem(pScrn, 0, 0x400000) / 1024;
1423		    break;
1424		case SMI_LYNX3DM:
1425		    pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024;
1426		    break;
1427		case SMI_COUGAR3DR:
1428		    /* DANGER - Cougar3DR BIOS is broken - hardcode video ram
1429		     * size per instructions from Silicon Motion engineers */
1430		    pSmi->videoRAMKBytes = 16 * 1024;
1431		    break;
1432		default:
1433		    pSmi->videoRAMKBytes = default_table[config >> 6] * 1024;
1434		    break;
1435	    }
1436	}
1437	from = X_PROBED;
1438    }
1439
1440    pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
1441    pScrn->videoRam     = pSmi->videoRAMKBytes;
1442    xf86DrvMsg(pScrn->scrnIndex, from,
1443	       "videoram: %dkB\n", pSmi->videoRAMKBytes);
1444
1445    return (TRUE);
1446}
1447
1448Bool
1449SMI_MapMem(ScrnInfoPtr pScrn)
1450{
1451    SMIPtr pSmi = SMIPTR(pScrn);
1452    vgaHWPtr hwp;
1453
1454    ENTER();
1455
1456    if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE)
1457	LEAVE(FALSE);
1458
1459    pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
1460
1461    if (pSmi->Chipset == SMI_LYNX3DM)
1462	pSmi->fbMapOffset = 0x200000;
1463    else
1464	pSmi->fbMapOffset = 0x0;
1465
1466#ifndef XSERVER_LIBPCIACCESS
1467    pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex,
1468				 VIDMEM_FRAMEBUFFER,
1469				 pSmi->PciTag,
1470				 pScrn->memPhysBase + pSmi->fbMapOffset,
1471				 pSmi->videoRAMBytes);
1472#else
1473    {
1474	void	**result = (void**)&pSmi->FBBase;
1475	int	  err = pci_device_map_range(pSmi->PciInfo,
1476					     pScrn->memPhysBase +
1477					     pSmi->fbMapOffset,
1478					     pSmi->videoRAMBytes,
1479					     PCI_DEV_MAP_FLAG_WRITABLE |
1480					     PCI_DEV_MAP_FLAG_WRITE_COMBINE,
1481					     result);
1482
1483	if (err)
1484	    LEAVE(FALSE);
1485    }
1486#endif
1487
1488    if (pSmi->FBBase == NULL) {
1489	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1490		   "Internal error: could not map framebuffer.\n");
1491	LEAVE(FALSE);
1492    }
1493
1494    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1495		   "Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
1496		   pScrn->memPhysBase, pSmi->fbMapOffset);
1497    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1498		   "Logical frame buffer at %p - %p\n", pSmi->FBBase,
1499		   pSmi->FBBase + pSmi->videoRAMBytes - 1);
1500
1501    if (IS_MSOC(pSmi)) {
1502	/* Reserve space for panel cursr, and crt if in dual head mode */
1503#if SMI_CURSOR_ALPHA_PLANE
1504	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
1505	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE);
1506#else
1507	pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
1508	    (pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE);
1509
1510# if SMI501_CLI_DEBUG
1511	if (pSmi->useEXA) {
1512	    pSmi->batch_active = FALSE;
1513	    pSmi->batch_length = 4096;
1514	    pSmi->FBReserved -= pSmi->batch_length << 3;
1515	    pSmi->batch_offset = pSmi->FBReserved;
1516	    pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset);
1517	    pSmi->batch_finish = -1;
1518	    pSmi->batch_index = 0;
1519	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1520		       "Using command list interpreter debug code\n");
1521	}
1522# endif
1523
1524#endif
1525    }
1526    else {
1527	/* Set up offset to hwcursor memory area, at the end of
1528	 * the frame buffer.
1529	 */
1530	pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE;
1531	/* set up the fifo reserved space */
1532	if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ {
1533	    CARD32 fifoOffset = 0;
1534	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1535				       0x46) << 3;
1536	    fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1537				       0x47) << 11;
1538	    fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
1539					0x49) & 0x1C) << 17;
1540	    pSmi->FBReserved = fifoOffset;	/* PDR#1074 */
1541	}
1542	else
1543	    pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
1544
1545	xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n",
1546		   (unsigned long)pSmi->FBCursorOffset);
1547
1548	/* Assign hwp->MemBase & IOBase here */
1549	hwp = VGAHWPTR(pScrn);
1550	if (pSmi->IOBase != NULL)
1551	    vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
1552	vgaHWGetIOBase(hwp);
1553
1554	/* Map the VGA memory when the primary video */
1555	if (xf86IsPrimaryPci(pSmi->PciInfo)) {
1556	    hwp->MapSize = 0x10000;
1557	    if (!vgaHWMapMem(pScrn))
1558		LEAVE(FALSE);
1559	    pSmi->PrimaryVidMapped = TRUE;
1560	}
1561    }
1562
1563    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n",
1564	       (unsigned long)pSmi->FBReserved);
1565
1566    LEAVE(TRUE);
1567}
1568
1569/* UnMapMem - contains half of pre-4.0 EnterLeave function.  The EnterLeave
1570 * function which en/disable access to IO ports and ext. regs
1571 */
1572
1573void
1574SMI_UnmapMem(ScrnInfoPtr pScrn)
1575{
1576    SMIPtr pSmi = SMIPTR(pScrn);
1577
1578    ENTER();
1579
1580    /* Unmap VGA mem if mapped. */
1581    if (pSmi->PrimaryVidMapped) {
1582	vgaHWUnmapMem(pScrn);
1583	pSmi->PrimaryVidMapped = FALSE;
1584    }
1585
1586    SMI_DisableMmio(pScrn);
1587
1588    if (pSmi->MapBase) {
1589#ifndef XSERVER_LIBPCIACCESS
1590	xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase,
1591			pSmi->MapSize);
1592#else
1593	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase,
1594			       pSmi->MapSize);
1595#endif
1596	pSmi->MapBase = NULL;
1597    }
1598
1599    if (pSmi->FBBase) {
1600#ifndef XSERVER_LIBPCIACCESS
1601	xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
1602			pSmi->videoRAMBytes);
1603#else
1604	pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase,
1605			       pSmi->videoRAMBytes);
1606#endif
1607	pSmi->FBBase = NULL;
1608    }
1609
1610    LEAVE();
1611}
1612
1613/* This gets called at the start of each server generation. */
1614
1615static Bool
1616SMI_ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
1617{
1618    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
1619    SMIPtr		pSmi = SMIPTR(pScrn);
1620    EntityInfoPtr	pEnt;
1621
1622    ENTER();
1623
1624    /* Map MMIO regs and framebuffer */
1625    if (!SMI_MapMem(pScrn))
1626	LEAVE(FALSE);
1627
1628    pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
1629
1630    if (!pSmi->pInt10 && pSmi->useBIOS) {
1631	pSmi->pInt10 = xf86InitInt10(pEnt->index);
1632    }
1633    if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
1634	pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
1635    }
1636
1637    /* Save the chip/graphics state */
1638    pSmi->Save(pScrn);
1639
1640    /* Fill in some needed pScrn fields */
1641    pScrn->vtSema = TRUE;
1642    pScrn->pScreen = pScreen;
1643
1644    pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
1645
1646    pSmi->fbArea = NULL;
1647    pSmi->FBOffset = 0;
1648    pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
1649
1650    /* Clear frame buffer */
1651    memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
1652
1653    /*
1654     * The next step is to setup the screen's visuals, and initialise the
1655     * framebuffer code.  In cases where the framebuffer's default choises for
1656     * things like visual layouts and bits per RGB are OK, this may be as simple
1657     * as calling the framebuffer's ScreenInit() function.  If not, the visuals
1658     * will need to be setup before calling a fb ScreenInit() function and fixed
1659     * up after.
1660     */
1661
1662    /*
1663     * Reset the visual list.
1664     */
1665    miClearVisualTypes();
1666
1667    /* Setup the visuals we support. */
1668
1669    if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
1670			  pScrn->rgbBits, pScrn->defaultVisual))
1671	LEAVE(FALSE);
1672
1673    if (!miSetPixmapDepths ())
1674	LEAVE(FALSE);
1675
1676    /*
1677     * Call the framebuffer layer's ScreenInit function
1678     */
1679
1680    DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
1681	  pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
1682    if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
1683		     pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
1684	LEAVE(FALSE);
1685
1686    xf86SetBlackWhitePixels(pScreen);
1687
1688    if (pScrn->bitsPerPixel > 8) {
1689	VisualPtr visual;
1690	/* Fixup RGB ordering */
1691	visual = pScreen->visuals + pScreen->numVisuals;
1692	while (--visual >= pScreen->visuals) {
1693	    if ((visual->class | DynamicClass) == DirectColor) {
1694		visual->offsetRed   = pScrn->offset.red;
1695		visual->offsetGreen = pScrn->offset.green;
1696		visual->offsetBlue  = pScrn->offset.blue;
1697		visual->redMask     = pScrn->mask.red;
1698		visual->greenMask   = pScrn->mask.green;
1699		visual->blueMask    = pScrn->mask.blue;
1700	    }
1701	}
1702    }
1703
1704    /* must be after RGB ordering fixed */
1705    fbPictureInit(pScreen, 0, 0);
1706
1707    /* Do the CRTC independent initialization */
1708    if(!SMI_HWInit(pScrn))
1709	LEAVE(FALSE);
1710
1711    /* Unless using EXA, regardless or using XAA or not, needs offscreen
1712     * management at least for video. */
1713    if (pSmi->NoAccel || !pSmi->useEXA) {
1714	int		numLines;
1715	BoxRec		AvailFBArea;
1716
1717	numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
1718	AvailFBArea.x1 = 0;
1719	AvailFBArea.y1 = 0;
1720	AvailFBArea.x2 = pScrn->virtualX;
1721	AvailFBArea.y2 = numLines;
1722
1723	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
1724		   "FrameBuffer Box: %d,%d - %d,%d\n",
1725		   AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
1726		   AvailFBArea.y2);
1727
1728	xf86InitFBManager(pScreen, &AvailFBArea);
1729    }
1730
1731    /* Initialize acceleration layer */
1732    if (!pSmi->NoAccel) {
1733	if (pSmi->useEXA && !SMI_EXAInit(pScreen))
1734	    LEAVE(FALSE);
1735	else if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
1736	    LEAVE(FALSE);
1737    }
1738
1739    /* Initialize the chosen modes */
1740    if (!xf86SetDesiredModes(pScrn))
1741	    LEAVE(FALSE);
1742
1743    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
1744		   "Done writing mode.  Register dump:\n");
1745    SMI_PrintRegs(pScrn);
1746
1747    miInitializeBackingStore(pScreen);
1748
1749#ifdef HAVE_XMODES
1750    xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
1751#endif
1752
1753    /* Initialise cursor functions */
1754    miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
1755
1756    /* Initialize HW cursor layer.  Must follow software cursor
1757     * initialization.
1758     */
1759    if (pSmi->HwCursor) {
1760	int	size, flags;
1761
1762	if (IS_MSOC(pSmi)) {
1763	    size = SMI501_MAX_CURSOR;
1764	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
1765		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
1766#if SMI_CURSOR_ALPHA_PLANE
1767	    if (!pSmi->Dualhead)
1768		flags |= HARDWARE_CURSOR_ARGB;
1769#endif
1770	}
1771	else {
1772	    size = SMILYNX_MAX_CURSOR;
1773	    flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
1774		     HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
1775		     HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
1776		     HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
1777		     HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
1778		     HARDWARE_CURSOR_INVERT_MASK);
1779	}
1780
1781	if (!xf86_cursors_init(pScreen, size, size, flags))
1782	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
1783		       "Hardware cursor initialization failed\n");
1784    }
1785
1786    /* Initialise default colormap */
1787    if (!miCreateDefColormap(pScreen))
1788	LEAVE(FALSE);
1789
1790    /* Initialize colormap layer.  Must follow initialization of the default
1791     * colormap.  And SetGamma call, else it will load palette with solid white.
1792     */
1793    if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
1794			     CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
1795	LEAVE(FALSE);
1796
1797    pScreen->SaveScreen = SMI_SaveScreen;
1798    pSmi->CloseScreen = pScreen->CloseScreen;
1799    pScreen->CloseScreen = SMI_CloseScreen;
1800
1801    if ((IS_MSOC(pSmi) &&
1802	 !xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
1803	(!IS_MSOC(pSmi) &&
1804	 !xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
1805	xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
1806
1807    SMI_InitVideo(pScreen);
1808
1809    if(!xf86CrtcScreenInit(pScreen))
1810	LEAVE(FALSE);
1811
1812    /* Report any unused options (only for the first generation) */
1813    if (serverGeneration == 1) {
1814	xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
1815    }
1816
1817    LEAVE(TRUE);
1818}
1819
1820/*
1821 * This is called at the end of each server generation.  It restores the
1822 * original (text) mode.  It should also unmap the video memory, and free any
1823 * per-generation data allocated by the driver.  It should finish by unwrapping
1824 * and calling the saved CloseScreen function.
1825 */
1826
1827static Bool
1828SMI_CloseScreen(int scrnIndex, ScreenPtr pScreen)
1829{
1830    ScrnInfoPtr	pScrn = xf86Screens[scrnIndex];
1831    SMIPtr	pSmi = SMIPTR(pScrn);
1832    Bool	ret;
1833
1834    ENTER();
1835
1836    if (pSmi->HwCursor)
1837	xf86_cursors_fini(pScreen);
1838
1839    if (pScrn->vtSema)
1840	/* Restore console mode and unmap framebuffer */
1841	SMI_LeaveVT(scrnIndex, 0);
1842
1843    if (pSmi->XAAInfoRec != NULL) {
1844	XAADestroyInfoRec(pSmi->XAAInfoRec);
1845    }
1846    if (pSmi->EXADriverPtr) {
1847	exaDriverFini(pScreen);
1848	pSmi->EXADriverPtr = NULL;
1849    }
1850    if (pSmi->pVbe != NULL) {
1851	vbeFree(pSmi->pVbe);
1852	pSmi->pVbe = NULL;
1853    }
1854    if (pSmi->pInt10 != NULL) {
1855	xf86FreeInt10(pSmi->pInt10);
1856	pSmi->pInt10 = NULL;
1857    }
1858    if (pSmi->ptrAdaptor != NULL) {
1859	xfree(pSmi->ptrAdaptor);
1860    }
1861    if (pSmi->BlockHandler != NULL) {
1862	pScreen->BlockHandler = pSmi->BlockHandler;
1863    }
1864
1865    pScrn->vtSema = FALSE;
1866    pScreen->CloseScreen = pSmi->CloseScreen;
1867    ret = (*pScreen->CloseScreen)(scrnIndex, pScreen);
1868
1869    LEAVE(ret);
1870}
1871
1872static void
1873SMI_FreeScreen(int scrnIndex, int flags)
1874{
1875    SMI_FreeRec(xf86Screens[scrnIndex]);
1876}
1877
1878static Bool
1879SMI_SaveScreen(ScreenPtr pScreen, int mode)
1880{
1881    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1882
1883    ENTER();
1884
1885    if(xf86IsUnblank(mode)){
1886	pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
1887    }else{
1888	pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
1889    }
1890
1891    LEAVE(TRUE);
1892}
1893
1894void
1895SMI_AdjustFrame(int scrnIndex, int x, int y, int flags)
1896{
1897    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(xf86Screens[scrnIndex]);
1898    xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
1899
1900    ENTER();
1901
1902    SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
1903
1904    LEAVE();
1905}
1906
1907Bool
1908SMI_SwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
1909{
1910    Bool ret;
1911    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
1912    SMIPtr pSmi = SMIPTR(pScrn);
1913
1914    ENTER();
1915
1916    ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
1917
1918    if (!pSmi->NoAccel)
1919	SMI_EngineReset(pScrn);
1920
1921    LEAVE(ret);
1922}
1923
1924void
1925SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
1926		LOCO *colors, VisualPtr pVisual)
1927{
1928    xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
1929    int crtc_idx,i,j;
1930
1931    ENTER();
1932
1933    if(pScrn->bitsPerPixel == 16){
1934	/* Expand the RGB 565 palette into the 256-elements LUT */
1935
1936	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
1937	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
1938
1939	    for(i=0; i<numColors; i++){
1940		int idx = indicies[i];
1941
1942		if(idx<32){
1943		    for(j=0; j<8; j++){
1944			crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
1945			crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
1946		    }
1947		}
1948
1949		for(j=0; j<4; j++)
1950		    crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
1951	    }
1952
1953	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
1954    }
1955    }else{
1956	for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
1957	    SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
1958
1959    for(i = 0; i < numColors; i++) {
1960		int idx = indicies[i];
1961
1962		crtcPriv->lut_r[idx] = colors[idx].red << 8;
1963		crtcPriv->lut_g[idx] = colors[idx].green << 8;
1964		crtcPriv->lut_b[idx] = colors[idx].blue << 8;
1965	    }
1966
1967	    crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
1968	}
1969    }
1970
1971    LEAVE();
1972}
1973
1974static void
1975SMI_DisableVideo(ScrnInfoPtr pScrn)
1976{
1977    SMIPtr pSmi = SMIPTR(pScrn);
1978    CARD8 tmp;
1979
1980    if (!IS_MSOC(pSmi)) {
1981	if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
1982	    return;
1983	pSmi->DACmask = tmp;
1984	VGAOUT8(pSmi, VGA_DAC_MASK, 0);
1985    }
1986}
1987
1988static void
1989SMI_EnableVideo(ScrnInfoPtr pScrn)
1990{
1991    SMIPtr pSmi = SMIPTR(pScrn);
1992
1993    if (!IS_MSOC(pSmi)) {
1994	VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
1995    }
1996}
1997
1998
1999void
2000SMI_EnableMmio(ScrnInfoPtr pScrn)
2001{
2002    SMIPtr pSmi = SMIPTR(pScrn);
2003
2004    ENTER();
2005
2006    if (!IS_MSOC(pSmi)) {
2007	vgaHWPtr hwp = VGAHWPTR(pScrn);
2008	CARD8 tmp;
2009
2010	/*
2011	 * Enable chipset (seen on uninitialized secondary cards) might not be
2012	 * needed once we use the VGA softbooter
2013	 */
2014	vgaHWSetStdFuncs(hwp);
2015
2016	/* Enable linear mode */
2017	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
2018	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
2019	pSmi->SR18Value = tmp;					/* PDR#521 */
2020	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp | 0x11);
2021
2022	/* Enable 2D/3D Engine and Video Processor */
2023	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
2024	tmp = inb(pSmi->PIOBase + VGA_SEQ_DATA);
2025	pSmi->SR21Value = tmp;					/* PDR#521 */
2026	outb(pSmi->PIOBase + VGA_SEQ_DATA, tmp & ~0x03);
2027    }
2028
2029    LEAVE();
2030}
2031
2032void
2033SMI_DisableMmio(ScrnInfoPtr pScrn)
2034{
2035    SMIPtr pSmi = SMIPTR(pScrn);
2036
2037    ENTER();
2038
2039    if (!IS_MSOC(pSmi)) {
2040	vgaHWPtr hwp = VGAHWPTR(pScrn);
2041
2042	vgaHWSetStdFuncs(hwp);
2043
2044	/* Disable 2D/3D Engine and Video Processor */
2045	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x21);
2046	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR21Value);	/* PDR#521 */
2047
2048	/* Disable linear mode */
2049	outb(pSmi->PIOBase + VGA_SEQ_INDEX, 0x18);
2050	outb(pSmi->PIOBase + VGA_SEQ_DATA, pSmi->SR18Value);	/* PDR#521 */
2051    }
2052
2053    LEAVE();
2054}
2055
2056static void
2057SMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
2058{
2059    vbeInfoPtr pVbe;
2060    if (xf86LoadSubModule(pScrn, "vbe")) {
2061	pVbe = VBEInit(NULL, index);
2062	ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
2063	vbeFree(pVbe);
2064    }
2065}
2066
2067static Bool
2068SMI_HWInit(ScrnInfoPtr pScrn)
2069{
2070    SMIPtr pSmi = SMIPTR(pScrn);
2071
2072    ENTER();
2073
2074    if(IS_MSOC(pSmi))
2075	LEAVE(SMI501_HWInit(pScrn));
2076    else
2077	LEAVE(SMILynx_HWInit(pScrn));
2078}
2079
2080void
2081SMI_PrintRegs(ScrnInfoPtr pScrn)
2082{
2083    SMIPtr pSmi = SMIPTR(pScrn);
2084    int i;
2085
2086    ENTER();
2087
2088    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
2089		"START register dump ------------------\n");
2090
2091    if(IS_MSOC(pSmi))
2092	SMI501_PrintRegs(pScrn);
2093    else
2094	SMILynx_PrintRegs(pScrn);
2095
2096
2097    xf86ErrorFVerb(VERBLEV, "\n\nDPR    x0       x4       x8       xC");
2098    for (i = 0x00; i <= 0x44; i += 4) {
2099	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
2100	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i));
2101    }
2102
2103    xf86ErrorFVerb(VERBLEV, "\n\nVPR    x0       x4       x8       xC");
2104    for (i = 0x00; i <= 0x60; i += 4) {
2105	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
2106	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i));
2107    }
2108
2109    xf86ErrorFVerb(VERBLEV, "\n\nCPR    x0       x4       x8       xC");
2110    for (i = 0x00; i <= 0x18; i += 4) {
2111	if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
2112	xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i));
2113    }
2114
2115    xf86ErrorFVerb(VERBLEV, "\n\n");
2116    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
2117		"END register dump --------------------\n");
2118
2119    LEAVE();
2120}
2121