Bug#974703: found pci_device_map_range returning EINVAL
Hello All,
Inserting some logging statements into the code, I found:
I was getting "Not enough video memory" error in SMI_PreInit() because
pSmi->FBReserved was 0.
pSmi->FBReserved was 0 because SMI_MapMem() (called earlier in
SMI_PreInit()) was exiting at an early if-statement, because
pSmi->MapBase was not already set and SMI_MapMmio() was returning FALSE.
SMI_MapMmio() was returning FALSE because its call to
pci_device_map_range() was returning EINVAL (decimal 22).
Looking at the code for pci_device_map_range() in libpciaccess
common_interface.c, it appears EINVAL is the return value for when the
"struct pci_device" passed in already has an existing mapping with the
same base and size.
However I do not find any "previous" call into pci_device_map_range
successfully creating the mapping that supposedly already exists.
Situation remains unresolved, still cannot startx.
My modified smi_driver.c and Xorg.0.log output attached.
Kind regards,
Michael Redman
--
Michael Redman
https://www.michael-redman.name
IN GOD WE TRVST.
/* Header: //Mercury/Projects/archives/XFree86/4.0/smi_driver.c-arc 1.42 03 Jan 2001 13:52:16 Frido $ */
/*
Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
Copyright (C) 2000 Silicon Motion, Inc. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FIT-
NESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the names of The XFree86 Project and
Silicon Motion shall not be used in advertising or otherwise to promote the
sale, use or other dealings in this Software without prior written
authorization from The XFree86 Project or Silicon Motion.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "xf86.h"
#include "xf86DDC.h"
#include "xf86int10.h"
#include "vbe.h"
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 6
#include "xf86Resources.h"
#include "xf86RAC.h"
#endif
#include "smi.h"
#include "smi_501.h"
#include "smilynx.h"
#include "smi_crtc.h"
#include "globals.h"
#ifdef HAVE_XEXTPROTO_71
#include <X11/extensions/dpmsconst.h>
#else
#define DPMS_SERVER
#include <X11/extensions/dpms.h>
#endif
#include <errno.h>
/*
* Internals
*/
static Bool SMI_MapMmio(ScrnInfoPtr pScrn);
static Bool SMI_DetectMem(ScrnInfoPtr pScrn);
static void SMI_EnableMmio(ScrnInfoPtr pScrn);
static void SMI_DisableMmio(ScrnInfoPtr pScrn);
static Bool SMI_HWInit(ScrnInfoPtr pScrn);
/*
* Forward definitions for the functions that make up the driver.
*/
static const OptionInfoRec * SMI_AvailableOptions(int chipid, int busid);
static void SMI_Identify(int flags);
static Bool SMI_Probe(DriverPtr drv, int flags);
static Bool SMI_PreInit(ScrnInfoPtr pScrn, int flags);
static Bool SMI_EnterVT(VT_FUNC_ARGS_DECL);
static void SMI_LeaveVT(VT_FUNC_ARGS_DECL);
static Bool SMI_ScreenInit(SCREEN_INIT_ARGS_DECL);
static void SMI_DisableVideo(ScrnInfoPtr pScrn);
static void SMI_EnableVideo(ScrnInfoPtr pScrn);
static Bool SMI_CloseScreen(CLOSE_SCREEN_ARGS_DECL);
static Bool SMI_SaveScreen(ScreenPtr pScreen, int mode);
static void SMI_FreeScreen(FREE_SCREEN_ARGS_DECL);
static void SMI_ProbeDDC(ScrnInfoPtr pScrn, int index);
static void SMI_DetectPanelSize(ScrnInfoPtr pScrn);
static void SMI_DetectMCLK(ScrnInfoPtr pScrn);
/*
* xf86VDrvMsgVerb prints up to 14 characters prefix, where prefix has the
* format "%s(%d): " so, use name "SMI" instead of "Silicon Motion"
*/
#define SILICONMOTION_NAME "SMI"
#define SILICONMOTION_DRIVER_NAME "siliconmotion"
#define SILICONMOTION_VERSION_NAME PACKAGE_VERSION
#define SILICONMOTION_VERSION_MAJOR PACKAGE_VERSION_MAJOR
#define SILICONMOTION_VERSION_MINOR PACKAGE_VERSION_MINOR
#define SILICONMOTION_PATCHLEVEL PACKAGE_VERSION_PATCHLEVEL
#define SILICONMOTION_DRIVER_VERSION ((SILICONMOTION_VERSION_MAJOR << 24) | \
(SILICONMOTION_VERSION_MINOR << 16) | \
(SILICONMOTION_PATCHLEVEL))
#if SMI_DEBUG
int smi_indent = 1;
#endif
/* for dualhead */
int gSMIEntityIndex = -1;
/*
* This contains the functions needed by the server after loading the
* driver module. It must be supplied, and gets added the driver list by
* the Module Setup funtion in the dynamic case. In the static case a
* reference to this is compiled in, and this requires that the name of
* this DriverRec be an upper-case version of the driver name.
*/
_X_EXPORT DriverRec SILICONMOTION =
{
SILICONMOTION_DRIVER_VERSION,
SILICONMOTION_DRIVER_NAME,
SMI_Identify,
SMI_Probe,
SMI_AvailableOptions,
NULL,
0
};
/* Supported chipsets */
static SymTabRec SMIChipsets[] =
{
{ PCI_CHIP_SMI910, "Lynx" },
{ PCI_CHIP_SMI810, "LynxE" },
{ PCI_CHIP_SMI820, "Lynx3D" },
{ PCI_CHIP_SMI710, "LynxEM" },
{ PCI_CHIP_SMI712, "LynxEM+" },
{ PCI_CHIP_SMI720, "Lynx3DM" },
{ PCI_CHIP_SMI731, "Cougar3DR" },
{ PCI_CHIP_SMI501, "MSOC" },
{ -1, NULL }
};
static PciChipsets SMIPciChipsets[] =
{
/* numChipset, PciID, Resource */
{ PCI_CHIP_SMI910, PCI_CHIP_SMI910, RES_SHARED_VGA },
{ PCI_CHIP_SMI810, PCI_CHIP_SMI810, RES_SHARED_VGA },
{ PCI_CHIP_SMI820, PCI_CHIP_SMI820, RES_SHARED_VGA },
{ PCI_CHIP_SMI710, PCI_CHIP_SMI710, RES_SHARED_VGA },
{ PCI_CHIP_SMI712, PCI_CHIP_SMI712, RES_SHARED_VGA },
{ PCI_CHIP_SMI720, PCI_CHIP_SMI720, RES_SHARED_VGA },
{ PCI_CHIP_SMI731, PCI_CHIP_SMI731, RES_SHARED_VGA },
{ PCI_CHIP_SMI501, PCI_CHIP_SMI501, RES_UNDEFINED },
{ -1, -1, RES_UNDEFINED }
};
typedef enum
{
OPTION_PCI_BURST,
OPTION_PCI_RETRY,
OPTION_NOACCEL,
OPTION_MCLK,
OPTION_MXCLK,
OPTION_SWCURSOR,
OPTION_HWCURSOR,
OPTION_VIDEOKEY,
OPTION_BYTESWAP,
/* CZ 26.10.2001: interlaced video */
OPTION_INTERLACED,
/* end CZ */
OPTION_USEBIOS,
OPTION_DUALHEAD,
OPTION_ACCELMETHOD,
OPTION_PANEL_SIZE,
OPTION_USE_FBDEV,
OPTION_CSCVIDEO,
NUMBER_OF_OPTIONS
} SMIOpts;
static const OptionInfoRec SMIOptions[] =
{
{ OPTION_PCI_BURST, "pci_burst", OPTV_BOOLEAN, {0}, TRUE },
{ OPTION_PCI_RETRY, "pci_retry", OPTV_BOOLEAN, {0}, TRUE },
{ OPTION_NOACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_MCLK, "MCLK", OPTV_FREQ, {0}, FALSE },
{ OPTION_MXCLK, "MXCLK", OPTV_FREQ, {0}, FALSE },
{ OPTION_HWCURSOR, "HWCursor", OPTV_BOOLEAN, {0}, TRUE },
{ OPTION_SWCURSOR, "SWCursor", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_VIDEOKEY, "VideoKey", OPTV_INTEGER, {0}, FALSE },
{ OPTION_BYTESWAP, "ByteSwap", OPTV_BOOLEAN, {0}, FALSE },
/* CZ 26.10.2001: interlaced video */
{ OPTION_INTERLACED, "Interlaced", OPTV_BOOLEAN, {0}, FALSE },
/* end CZ */
{ OPTION_USEBIOS, "UseBIOS", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_DUALHEAD, "Dualhead", OPTV_BOOLEAN, {0}, TRUE },
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
{ OPTION_PANEL_SIZE, "PanelSize", OPTV_ANYSTR, {0}, FALSE },
{ OPTION_USE_FBDEV, "UseFBDev", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_CSCVIDEO, "CSCVideo", OPTV_BOOLEAN, {0}, TRUE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
#ifdef XFree86LOADER
static MODULESETUPPROTO(siliconmotionSetup);
static XF86ModuleVersionInfo SMIVersRec =
{
"siliconmotion",
MODULEVENDORSTRING,
MODINFOSTRING1,
MODINFOSTRING2,
XORG_VERSION_CURRENT,
SILICONMOTION_VERSION_MAJOR,
SILICONMOTION_VERSION_MINOR,
SILICONMOTION_PATCHLEVEL,
ABI_CLASS_VIDEODRV,
ABI_VIDEODRV_VERSION,
MOD_CLASS_VIDEODRV,
{0, 0, 0, 0}
};
/*
* This is the module init data for XFree86 modules.
*
* Its name has to be the driver name followed by ModuleData.
*/
_X_EXPORT XF86ModuleData siliconmotionModuleData =
{
&SMIVersRec,
siliconmotionSetup,
NULL
};
static pointer
siliconmotionSetup(pointer module, pointer opts, int *errmaj, int *errmin)
{
static Bool setupDone = FALSE;
if (!setupDone) {
setupDone = TRUE;
xf86AddDriver(&SILICONMOTION, module, 0);
/*
* The return value must be non-NULL on success even though there
* is no TearDownProc.
*/
return (pointer) 1;
} else {
if (errmaj) {
*errmaj = LDR_ONCEONLY;
}
return NULL;
}
}
#endif /* XFree86LOADER */
static Bool
SMI_GetRec(ScrnInfoPtr pScrn)
{
ENTER();
/*
* Allocate an 'Chip'Rec, and hook it into pScrn->driverPrivate.
* pScrn->driverPrivate is initialised to NULL, so we can check if
* the allocation has already been done.
*/
if (pScrn->driverPrivate == NULL) {
pScrn->driverPrivate = xnfcalloc(sizeof(SMIRec), 1);
}
LEAVE(TRUE);
}
static void
SMI_FreeRec(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
if (pSmi) {
free(pSmi->save);
free(pSmi->mode);
free(pScrn->driverPrivate);
pScrn->driverPrivate = NULL;
}
LEAVE();
}
static const OptionInfoRec *
SMI_AvailableOptions(int chipid, int busid)
{
ENTER();
LEAVE(SMIOptions);
}
static void
SMI_Identify(int flags)
{
ENTER();
xf86PrintChipsets(SILICONMOTION_NAME, "driver (version "
SILICONMOTION_VERSION_NAME ") for Silicon Motion Lynx chipsets",
SMIChipsets);
LEAVE();
}
static Bool
SMI_Probe(DriverPtr drv, int flags)
{
int i;
GDevPtr *devSections;
int *usedChips;
int numDevSections;
int numUsed;
Bool foundScreen = FALSE;
ENTER();
numDevSections = xf86MatchDevice(SILICONMOTION_DRIVER_NAME, &devSections);
if (numDevSections <= 0)
/* There's no matching device section in the config file, so quit now. */
LEAVE(FALSE);
#ifndef XSERVER_LIBPCIACCESS
if (xf86GetPciVideoInfo() == NULL)
LEAVE(FALSE);
#endif
numUsed = xf86MatchPciInstances(SILICONMOTION_NAME, PCI_SMI_VENDOR_ID,
SMIChipsets, SMIPciChipsets, devSections,
numDevSections, drv, &usedChips);
/* Free it since we don't need that list after this */
free(devSections);
if (numUsed <= 0)
LEAVE(FALSE);
if (flags & PROBE_DETECT)
foundScreen = TRUE;
else {
ScrnInfoPtr pScrn;
EntityInfoPtr pEnt;
for (i = 0; i < numUsed; i++) {
if ((pScrn = xf86ConfigPciEntity(NULL, 0, usedChips[i],
SMIPciChipsets, NULL,
NULL, NULL, NULL, NULL))) {
pScrn->driverVersion = SILICONMOTION_DRIVER_VERSION;
pScrn->driverName = SILICONMOTION_DRIVER_NAME;
pScrn->name = SILICONMOTION_NAME;
pScrn->Probe = SMI_Probe;
pScrn->PreInit = SMI_PreInit;
pScrn->ScreenInit = SMI_ScreenInit;
pScrn->SwitchMode = SMI_SwitchMode;
pScrn->AdjustFrame = SMI_AdjustFrame;
if ((pEnt = xf86GetEntityInfo(usedChips[i]))) {
pScrn->EnterVT = SMI_EnterVT;
pScrn->LeaveVT = SMI_LeaveVT;
free(pEnt);
}
pScrn->FreeScreen = SMI_FreeScreen;
foundScreen = TRUE;
}
}
}
free(usedChips);
LEAVE(foundScreen);
}
static Bool
SMI_PreInit(ScrnInfoPtr pScrn, int flags)
{
EntityInfoPtr pEnt;
SMIPtr pSmi;
MessageType from;
vgaHWPtr hwp;
ENTER();
/* Ignoring the Type list for now. It might be needed when multiple cards
* are supported.
*/
if (pScrn->numEntities > 1)
LEAVE(FALSE);
/* Allocate the SMIRec driverPrivate */
if (!SMI_GetRec(pScrn))
LEAVE(FALSE);
pSmi = SMIPTR(pScrn);
/* Find the PCI slot for this screen */
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
if (IS_MSOC(pSmi)) {
pSmi->Save = SMI501_Save;
pSmi->save = xnfcalloc(sizeof(MSOCRegRec), 1);
pSmi->mode = xnfcalloc(sizeof(MSOCRegRec), 1);
}
else {
pSmi->Save = SMILynx_Save;
pSmi->save = xnfcalloc(sizeof(SMIRegRec), 1);
pSmi->mode = xnfcalloc(sizeof(SMIRegRec), 1);
}
if (flags & PROBE_DETECT) {
if (!IS_MSOC(pSmi))
SMI_ProbeDDC(pScrn, xf86GetEntityInfo(pScrn->entityList[0])->index);
LEAVE(TRUE);
}
if (pEnt->location.type != BUS_PCI) {
free(pEnt);
SMI_FreeRec(pScrn);
LEAVE(FALSE);
}
pSmi->PciInfo = xf86GetPciInfoForEntity(pEnt->index);
/* Set pScrn->monitor */
pScrn->monitor = pScrn->confScreen->monitor;
if (!IS_MSOC(pSmi)) {
/* The vgahw module should be loaded here when needed */
if (!xf86LoadSubModule(pScrn, "vgahw"))
LEAVE(FALSE);
/*
* Allocate a vgaHWRec
*/
if (!vgaHWGetHWRec(pScrn))
LEAVE(FALSE);
hwp = VGAHWPTR(pScrn);
vgaHWSetStdFuncs(hwp);
#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) < 12
pSmi->PIOBase = hwp->PIOOffset;
#else
pSmi->PIOBase = 0;
#ifdef XSERVER_LIBPCIACCESS
pSmi->io = hwp->io;
#endif
#endif
xf86ErrorFVerb(VERBLEV, "\tSMI_PreInit vgaCRIndex=%x, vgaIOBase=%x, "
"MMIOBase=%p\n", hwp->IOBase + VGA_CRTC_INDEX_OFFSET,
hwp->IOBase, hwp->MMIOBase);
}
/*
* The first thing we should figure out is the depth, bpp, etc.
*/
if (!xf86SetDepthBpp(pScrn, 0, 0, 0, Support32bppFb))
LEAVE(FALSE);
/* Check that the returned depth is one we support */
if (pScrn->depth != 8 && pScrn->depth != 16 && pScrn->depth != 24) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given depth (%d) is not supported by this driver\n",
pScrn->depth);
LEAVE(FALSE);
}
if(pScrn->bitsPerPixel != 8 && pScrn->bitsPerPixel != 16 &&
pScrn->bitsPerPixel != 24 && pScrn->bitsPerPixel != 32){
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Given bpp (%d) is not supported by this driver\n",
pScrn->bitsPerPixel);
LEAVE(FALSE);
}
xf86PrintDepthBpp(pScrn);
pSmi->Bpp = pScrn->bitsPerPixel >> 3;
/*
* This must happen after pScrn->display has been set because
* xf86SetWeight references it.
*/
if (pScrn->depth > 8) {
/* The defaults are OK for us */
rgb zeros = {0, 0, 0};
#if X_BYTE_ORDER == X_BIG_ENDIAN
rgb masks = {0xff00,0xff0000,0xff000000};
#else
rgb masks = {0, 0, 0};
#endif
if (!xf86SetWeight(pScrn, zeros, masks))
LEAVE(FALSE);
}
if (!xf86SetDefaultVisual(pScrn, -1))
LEAVE(FALSE);
/* We don't currently support DirectColor at > 8bpp */
if (pScrn->depth > 8 && pScrn->defaultVisual != TrueColor) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Given default visual (%s) "
"is not supported at depth %d\n",
xf86GetVisualName(pScrn->defaultVisual), pScrn->depth);
LEAVE(FALSE);
}
/* We use a programmable clock */
pScrn->progClock = TRUE;
/* Collect all of the relevant option flags (fill in pScrn->options) */
xf86CollectOptions(pScrn, NULL);
/* Set the bits per RGB for 8bpp mode */
if (pScrn->depth == 8){
pScrn->rgbBits = IS_MSOC(pSmi) ? 8 : 6;
}else if(pScrn->depth == 16){
/* Use 8 bit LUT for gamma correction*/
pScrn->rgbBits = 8;
}
/* Process the options */
if (!(pSmi->Options = malloc(sizeof(SMIOptions))))
LEAVE(FALSE);
memcpy(pSmi->Options, SMIOptions, sizeof(SMIOptions));
xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, pSmi->Options);
/* Enable pci burst by default */
from = X_DEFAULT;
pSmi->PCIBurst = TRUE;
if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_BURST, &pSmi->PCIBurst))
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, from, "PCI Burst %sabled\n",
pSmi->PCIBurst ? "en" : "dis");
/* Pci retry enabled by default if pci burst also enabled */
from = X_DEFAULT;
pSmi->PCIRetry = pSmi->PCIBurst ? TRUE : FALSE;
if (xf86GetOptValBool(pSmi->Options, OPTION_PCI_RETRY, &pSmi->PCIRetry)) {
from = X_CONFIG;
if (pSmi->PCIRetry && !pSmi->PCIBurst) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"\"pci_retry\" option requires \"pci_burst\".\n");
pSmi->PCIRetry = FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "PCI Retry %sabled\n",
pSmi->PCIRetry ? "en" : "dis");
if (xf86ReturnOptValBool(pSmi->Options, OPTION_NOACCEL, FALSE)) {
pSmi->NoAccel = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: NoAccel - Acceleration "
"disabled\n");
} else {
pSmi->NoAccel = FALSE;
}
if (IS_MSOC(pSmi)) {
from = X_DEFAULT;
if (xf86GetOptValBool(pSmi->Options, OPTION_USE_FBDEV, &pSmi->UseFBDev))
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, from, "UseFBDev %s.\n",
pSmi->UseFBDev ? "enabled" : "disabled");
}
from = X_CONFIG;
pSmi->HwCursor = TRUE;
/* SWCursor overrides HWCusor if both specified */
if (xf86ReturnOptValBool(pSmi->Options, OPTION_SWCURSOR, FALSE))
pSmi->HwCursor = FALSE;
else if (!xf86GetOptValBool(pSmi->Options, OPTION_HWCURSOR, &pSmi->HwCursor))
from = X_DEFAULT;
xf86DrvMsg(pScrn->scrnIndex, from, "Using %sware Cursor\n",
pSmi->HwCursor ? "Hard" : "Soft");
if (xf86GetOptValInteger(pSmi->Options, OPTION_VIDEOKEY, &pSmi->videoKey)) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Video key set to "
"0x%08X\n", pSmi->videoKey);
} else {
pSmi->videoKey = (1 << pScrn->offset.red) |
(1 << pScrn->offset.green) |
(((pScrn->mask.blue >> pScrn->offset.blue) - 1)
<< pScrn->offset.blue);
}
if (xf86ReturnOptValBool(pSmi->Options, OPTION_BYTESWAP, FALSE)) {
pSmi->ByteSwap = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: ByteSwap enabled.\n");
} else {
pSmi->ByteSwap = FALSE;
}
/* CZ 26.10.2001: interlaced video */
if (xf86ReturnOptValBool(pSmi->Options, OPTION_INTERLACED, FALSE)) {
pSmi->interlaced = TRUE;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: Interlaced enabled.\n");
} else {
pSmi->interlaced = FALSE;
}
/* end CZ */
if (IS_MSOC(pSmi))
pSmi->useBIOS = FALSE;
else if (xf86GetOptValBool(pSmi->Options, OPTION_USEBIOS, &pSmi->useBIOS)) {
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Option: UseBIOS %s.\n",
pSmi->useBIOS ? "enabled" : "disabled");
}
else if(pSmi->Chipset == SMI_LYNX3DM){
/* Default to UseBIOS disabled. */
pSmi->useBIOS = FALSE;
}
else {
/* Default to UseBIOS enabled. */
pSmi->useBIOS = TRUE;
}
if (pSmi->useBIOS) {
if (xf86LoadSubModule(pScrn,"int10")) {
pSmi->pInt10 = xf86InitInt10(pEnt->index);
}
if (pSmi->pInt10 && xf86LoadSubModule(pScrn, "vbe")) {
pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
}
if(!pSmi->pVbe){
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VBE initialization failed: falling back to UseBIOS disabled.\n");
pSmi->useBIOS = FALSE;
}
}
#ifndef XSERVER_LIBPCIACCESS
xf86RegisterResources(pEnt->index, NULL, ResExclusive);
#endif
/*
* Set the Chipset and ChipRev, allowing config file entries to
* override.
*/
if (pEnt->device->chipset && *pEnt->device->chipset) {
pScrn->chipset = pEnt->device->chipset;
pSmi->Chipset = xf86StringToToken(SMIChipsets, pScrn->chipset);
from = X_CONFIG;
}
else if (pEnt->device->chipID >= 0) {
pSmi->Chipset = pEnt->device->chipID;
pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
from = X_CONFIG;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipID override: 0x%04X\n",
pSmi->Chipset);
}
else {
from = X_PROBED;
pSmi->Chipset = PCI_DEV_DEVICE_ID(pSmi->PciInfo);
pScrn->chipset = (char *) xf86TokenToString(SMIChipsets, pSmi->Chipset);
}
if (pEnt->device->chipRev >= 0) {
pSmi->ChipRev = pEnt->device->chipRev;
xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ChipRev override: %d\n",
pSmi->ChipRev);
}
else
pSmi->ChipRev = PCI_DEV_REVISION(pSmi->PciInfo);
free(pEnt);
/*
* This shouldn't happen because such problems should be caught in
* SMI_Probe(), but check it just in case.
*/
if (pScrn->chipset == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "ChipID 0x%04X is not "
"recognised\n", pSmi->Chipset);
LEAVE(FALSE);
}
if (pSmi->Chipset < 0) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Chipset \"%s\" is not "
"recognised\n", pScrn->chipset);
LEAVE(FALSE);
}
xf86DrvMsg(pScrn->scrnIndex, from, "Chipset: \"%s\"\n", pScrn->chipset);
#ifndef XSERVER_LIBPCIACCESS
pSmi->PciTag = pciTag(pSmi->PciInfo->bus, pSmi->PciInfo->device,
pSmi->PciInfo->func);
#endif
from = X_DEFAULT;
if(pSmi->Chipset == SMI_LYNX3DM &&
pScrn->bitsPerPixel == 16)
pSmi->Dualhead = TRUE;
else
pSmi->Dualhead = FALSE;
if (xf86GetOptValBool(pSmi->Options, OPTION_DUALHEAD, &pSmi->Dualhead))
from = X_CONFIG;
if (IS_MSOC(pSmi)) {
pSmi->lcd = TRUE;
if (pSmi->Dualhead && pSmi->UseFBDev) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Dual head disabled in fbdev mode\n");
pSmi->Dualhead = FALSE;
}
/* FIXME Randr cursor code only works properly when argb cursors
* are also supported.
* FIXME This probably is a randr cursor bug, and since access to
* hw/xfree86/ramdac/xf86CursorPriv.h:xf86CursorScreenRec.SWCursor
* field is not available, one cannot easily workaround the problem,
* so, just disable it...
* TODO Check with a X Server newer then 1.4.0.90 (that is being
* used in the 502 OEM image).
* */
if (pSmi->Dualhead && pSmi->HwCursor) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"HW Cursor disabled in dual head mode\n");
pSmi->HwCursor = FALSE;
}
}
else if (SMI_LYNXM_SERIES(pSmi->Chipset)) {
/* tweak options for dualhead */
if (pSmi->Dualhead) {
pSmi->useBIOS = FALSE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "UseBIOS disabled in dualhead mode\n");
pSmi->HwCursor = FALSE;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "No hardware cursor in dualhead mode\n");
if (pScrn->bitsPerPixel != 16) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Dualhead only supported at "
"depth 16\n");
LEAVE(FALSE);
}
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "Dual head %sabled\n",
pSmi->Dualhead ? "en" : "dis");
if (!pSmi->NoAccel) {
char *strptr;
from = X_DEFAULT;
if ((strptr = (char *)xf86GetOptValString(pSmi->Options,
OPTION_ACCELMETHOD))) {
if (!xf86NameCmp(strptr,"XAA")) {
from = X_CONFIG;
pSmi->useEXA = FALSE;
} else if(!xf86NameCmp(strptr,"EXA")) {
from = X_CONFIG;
pSmi->useEXA = TRUE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "Using %s acceleration architecture\n",
pSmi->useEXA ? "EXA" : "XAA");
}
if (IS_MSOC(pSmi)) {
pSmi->CSCVideo = !pSmi->useEXA || !pSmi->Dualhead;
from = X_DEFAULT;
if (xf86GetOptValBool(pSmi->Options, OPTION_CSCVIDEO, &pSmi->CSCVideo)) {
from = X_CONFIG;
/* FIXME */
if (pSmi->CSCVideo && pSmi->useEXA && pSmi->Dualhead) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"CSCVideo requires XAA or EXA in single head mode.\n");
pSmi->CSCVideo = FALSE;
}
}
xf86DrvMsg(pScrn->scrnIndex, from, "CSC Video %sabled\n",
pSmi->CSCVideo ? "en" : "dis");
}
SMI_MapMmio(pScrn);
SMI_DetectMem(pScrn);
SMI_MapMem(pScrn);
SMI_DisableVideo(pScrn);
/* detect the panel size */
SMI_DetectPanelSize(pScrn);
if(!IS_MSOC(pSmi)){
if (xf86LoadSubModule(pScrn, "i2c")) {
SMI_I2CInit(pScrn);
}
xf86LoadSubModule(pScrn, "ddc");
}
/*
* If the driver can do gamma correction, it should call xf86SetGamma()
*/
{
Gamma zeros = { 0.0, 0.0, 0.0 };
if (!xf86SetGamma(pScrn, zeros)) {
SMI_EnableVideo(pScrn);
SMI_UnmapMem(pScrn);
LEAVE(FALSE);
}
}
SMI_DetectMCLK(pScrn);
/*
* Setup the ClockRanges, which describe what clock ranges are available,
* and what sort of modes they can be used for.
*/
pSmi->clockRange.next = NULL;
pSmi->clockRange.minClock = 20000;
if (SMI_LYNXM_SERIES(pSmi->Chipset) ||
IS_MSOC(pSmi))
pSmi->clockRange.maxClock = 200000;
else
pSmi->clockRange.maxClock = 135000;
pSmi->clockRange.clockIndex = -1;
pSmi->clockRange.interlaceAllowed = FALSE;
pSmi->clockRange.doubleScanAllowed = FALSE;
if(!SMI_CrtcPreInit(pScrn))
LEAVE(FALSE);
if(!SMI_OutputPreInit(pScrn))
LEAVE(FALSE);
/* Only allow growing the screen dimensions if EXA is being used */
if (!xf86InitialConfiguration (pScrn, !pSmi->NoAccel && pSmi->useEXA)){
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes found\n");
SMI_EnableVideo(pScrn);
SMI_UnmapMem(pScrn);
LEAVE(FALSE);
}
/* Ensure that the framebuffer size just set fits in video memory. */
{
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "pSmi->Bpp %d\n",pSmi->Bpp);
int aligned_pitch = (pScrn->virtualX*pSmi->Bpp + 15) & ~15;
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "aligned_pitch %d\n",aligned_pitch);
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_PreInit: pSmi->FBReserved %lu\n",pSmi->FBReserved);
if(aligned_pitch * pScrn->virtualY > pSmi->FBReserved){
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Not enough video memory "
"for the configured screen size (%dx%d) and color depth.\n",
pScrn->virtualX, pScrn->virtualY);
SMI_EnableVideo(pScrn);
SMI_UnmapMem(pScrn);
LEAVE(FALSE);
}
}
SMI_EnableVideo(pScrn);
SMI_UnmapMem(pScrn);
if(pSmi->pVbe){
vbeFree(pSmi->pVbe);
pSmi->pVbe = NULL;
}
if(pSmi->pInt10){
xf86FreeInt10(pSmi->pInt10);
pSmi->pInt10 = NULL;
}
/* Set display resolution */
xf86SetDpi(pScrn, 0, 0);
if (xf86LoadSubModule(pScrn, "fb") == NULL) {
SMI_FreeRec(pScrn);
LEAVE(FALSE);
}
/* Load XAA or EXA if needed */
if (!pSmi->NoAccel) {
if (!pSmi->useEXA) {
if (!xf86LoadSubModule(pScrn, "xaa")) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "No acceleration\n");
pSmi->NoAccel = 1;
}
} else {
XF86ModReqInfo req;
int errmaj, errmin;
memset(&req, 0, sizeof(XF86ModReqInfo));
req.majorversion = 2;
req.minorversion = 1;
if (!LoadSubModule(pScrn->module, "exa", NULL, NULL, NULL,
&req, &errmaj, &errmin)) {
LoaderErrorMsg(NULL, "exa", errmaj, errmin);
SMI_FreeRec(pScrn);
LEAVE(FALSE);
}
}
}
/* Load ramdac if needed */
if (pSmi->HwCursor) {
if (!xf86LoadSubModule(pScrn, "ramdac")) {
SMI_FreeRec(pScrn);
LEAVE(FALSE);
}
}
LEAVE(TRUE);
}
/*
* This is called when VT switching back to the X server. Its job is to
* reinitialise the video mode. We may wish to unmap video/MMIO memory too.
*/
static Bool
SMI_EnterVT(VT_FUNC_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
/* Enable MMIO and map memory */
SMI_MapMem(pScrn);
pSmi->Save(pScrn);
/* FBBase may have changed after remapping the memory */
pScrn->pScreen->ModifyPixmapHeader(pScrn->pScreen->GetScreenPixmap(pScrn->pScreen),
-1,-1,-1,-1,-1, pSmi->FBBase + pSmi->FBOffset);
#if (XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 9, 99, 1, 0))
pScrn->pixmapPrivate.ptr=pSmi->FBBase + pSmi->FBOffset;
#endif
if(pSmi->useEXA)
pSmi->EXADriverPtr->memoryBase=pSmi->FBBase;
/* Do the CRTC independent initialization */
if(!SMI_HWInit(pScrn))
LEAVE(FALSE);
/* Initialize the chosen modes */
if (!xf86SetDesiredModes(pScrn))
LEAVE(FALSE);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Done writing mode. Register dump:\n");
SMI_PrintRegs(pScrn);
/* Reset the grapics engine */
if (!pSmi->NoAccel)
SMI_EngineReset(pScrn);
LEAVE(TRUE);
}
/*
* This is called when VT switching away from the X server. Its job is to
* restore the previous (text) mode. We may wish to remap video/MMIO memory
* too.
*/
static void
SMI_LeaveVT(VT_FUNC_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
SMI_AccelSync(pScrn);
/* Ensure that the rotation BlockHandler is unwrapped, and the shadow
pixmaps are deallocated, as the video memory is going to be
unmapped. */
xf86RotateCloseScreen(pScrn->pScreen);
/* Pixmaps that by chance get allocated near the former aperture
address shouldn't be considered offscreen. */
if(pSmi->useEXA)
pSmi->EXADriverPtr->memoryBase=NULL;
/* Clear frame buffer */
memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
if (!IS_MSOC(pSmi)) {
vgaHWPtr hwp = VGAHWPTR(pScrn);
SMILynx_WriteMode(pScrn, &hwp->SavedReg, pSmi->save);
}
else
SMI501_WriteMode(pScrn, pSmi->save);
SMI_UnmapMem(pScrn);
LEAVE();
}
static void
SMI_DetectPanelSize(ScrnInfoPtr pScrn)
{
const char *s;
int width, height;
SMIPtr pSmi = SMIPTR(pScrn);
pSmi->lcdWidth = 0;
pSmi->lcdHeight = 0;
if ((s = xf86GetOptValString(pSmi->Options, OPTION_PANEL_SIZE)) != NULL) {
if (sscanf(s, "%dx%d", &width, &height) != 2)
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Invalid PanelSize option: %s\n", s);
else {
pSmi->lcdWidth = width;
pSmi->lcdHeight = height;
}
}
if (pSmi->lcdWidth == 0 || pSmi->lcdHeight == 0) {
/* panel size detection ... requires BIOS call on 730 hardware */
if (pSmi->Chipset == SMI_COUGAR3DR) {
if (pSmi->pInt10 != NULL) {
pSmi->pInt10->num = 0x10;
pSmi->pInt10->ax = 0x5F00;
pSmi->pInt10->bx = 0;
pSmi->pInt10->cx = 0;
pSmi->pInt10->dx = 0;
xf86ExecX86int10(pSmi->pInt10);
if (pSmi->pInt10->ax == 0x005F) {
switch (pSmi->pInt10->cx & 0x0F) {
case PANEL_640x480:
pSmi->lcdWidth = 640;
pSmi->lcdHeight = 480;
break;
case PANEL_800x600:
pSmi->lcdWidth = 800;
pSmi->lcdHeight = 600;
break;
case PANEL_1024x768:
pSmi->lcdWidth = 1024;
pSmi->lcdHeight = 768;
break;
case PANEL_1280x1024:
pSmi->lcdWidth = 1280;
pSmi->lcdHeight = 1024;
break;
case PANEL_1600x1200:
pSmi->lcdWidth = 1600;
pSmi->lcdHeight = 1200;
break;
case PANEL_1400x1050:
pSmi->lcdWidth = 1400;
pSmi->lcdHeight = 1050;
break;
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Detected panel size via BIOS: %d x %d\n",
pSmi->lcdWidth, pSmi->lcdHeight);
}
else
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"BIOS error during 730 panel detection!\n");
}
else {
/* int10 support isn't setup on the second call to this function,
o if this is the second call, don't do detection again */
if (pSmi->lcd == 0)
/* If we get here, int10 support is not loaded or not working */
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"No BIOS support for 730 panel detection!\n");
}
/* Set this to indicate that we've done the detection */
pSmi->lcd = 1;
}
else if (IS_MSOC(pSmi)) {
pSmi->lcdWidth = (READ_SCR(pSmi, PANEL_WWIDTH) >> 16) & 2047;
pSmi->lcdHeight = (READ_SCR(pSmi, PANEL_WHEIGHT) >> 16) & 2047;
}
else {
/* panel size detection for hardware other than 730 */
pSmi->lcd = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x31) & 0x01;
if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x30) & 0x01) {
pSmi->lcd <<= 1;
}
switch (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x30) & 0x0C) {
case 0x00:
pSmi->lcdWidth = 640;
pSmi->lcdHeight = 480;
break;
case 0x04:
pSmi->lcdWidth = 800;
pSmi->lcdHeight = 600;
break;
case 0x08:
if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x74) & 0x02) {
pSmi->lcdWidth = 1024;
pSmi->lcdHeight = 600;
}
else {
pSmi->lcdWidth = 1024;
pSmi->lcdHeight = 768;
}
break;
case 0x0C:
pSmi->lcdWidth = 1280;
pSmi->lcdHeight = 1024;
break;
}
}
}
if (!pSmi->lcdWidth && (pSmi->lcdWidth = pScrn->virtualX) == 0)
pSmi->lcdWidth = 1024;
if (!pSmi->lcdHeight && (pSmi->lcdHeight = pScrn->virtualY) == 0)
pSmi->lcdHeight = 768;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "%s Panel Size = %dx%d\n",
(pSmi->lcd == 0) ? "OFF" : (pSmi->lcd == 1) ? "TFT" : "DSTN",
pSmi->lcdWidth, pSmi->lcdHeight);
}
static void
SMI_DetectMCLK(ScrnInfoPtr pScrn)
{
double real;
MSOCClockRec clock;
int mclk, mxclk;
SMIPtr pSmi = SMIPTR(pScrn);
/* MCLK defaults */
if (pSmi->Chipset == SMI_LYNXEMplus){
/* The SM712 can be safely clocked up to 157MHz, according to
Silicon Motion engineers. */
pSmi->MCLK = 157000;
} else if (IS_MSOC(pSmi)) {
/* Set some sane defaults for the clock settings if we are on a
SM502 and it's likely to be uninitialized. */
if (!xf86IsPrimaryPci(pSmi->PciInfo) &&
(READ_SCR(pSmi, DEVICE_ID) & 0xFF) >= 0xC0) {
pSmi->MCLK = 112000;
pSmi->MXCLK = 144000;
}
} else {
pSmi->MCLK = 0;
pSmi->MXCLK = 0;
}
/* MCLK from user settings */
if (xf86GetOptValFreq(pSmi->Options, OPTION_MCLK, OPTUNITS_MHZ, &real)) {
if (IS_MSOC(pSmi) || (int)real <= 120) {
pSmi->MCLK = (int)(real * 1000.0);
} else {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
"Memory Clock %1.3f MHz larger than limit of 120 MHz\n",
real);
}
}
mclk = pSmi->MCLK;
if (IS_MSOC(pSmi)) {
clock.value = READ_SCR(pSmi, CURRENT_CLOCK);
if (xf86GetOptValFreq(pSmi->Options, OPTION_MXCLK,
OPTUNITS_MHZ, &real))
pSmi->MXCLK = (int)(real * 1000.0);
}
/* Already programmed MCLK */
if (pSmi->MCLK == 0) {
if (IS_MSOC(pSmi))
mclk = ((clock.f.m_select ? 336 : 288) /
((clock.f.m_divider ? 3 : 1) <<
(unsigned)clock.f.m_shift)) * 1000;
else {
unsigned char shift, m, n;
m = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6A);
n = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x6B);
switch (n >> 6) {
case 1:
shift = 4;
break;
case 2:
shift = 2;
break;
default:
shift = 1;
break;
}
n &= 0x3F;
mclk = ((1431818 * m) / n / shift + 50) / 100;
}
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MCLK = %1.3f\n", mclk / 1000.0);
if (IS_MSOC(pSmi)) {
if (pSmi->MXCLK == 0) {
mxclk = ((clock.f.m1_select ? 336 : 288) /
((clock.f.m1_divider ? 3 : 1) <<
(unsigned)clock.f.m1_shift)) * 1000;
}
else
mxclk = pSmi->MXCLK;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "MXCLK = %1.3f\n", mxclk / 1000.0);
}
}
static Bool
SMI_MapMmio(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
CARD32 memBase;
SMI_EnableMmio(pScrn);
switch (pSmi->Chipset) {
case SMI_COUGAR3DR:
memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
pSmi->MapSize = 0x200000;
break;
case SMI_LYNX3D:
memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x680000;
pSmi->MapSize = 0x180000;
break;
case SMI_LYNXEM:
case SMI_LYNXEMplus:
memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
pSmi->MapSize = 0x400000;
break;
case SMI_LYNX3DM:
memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
pSmi->MapSize = 0x200000;
break;
case SMI_MSOC:
memBase = PCI_REGION_BASE(pSmi->PciInfo, 1, REGION_MEM);
pSmi->MapSize = 0x200000;
break;
default:
memBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + 0x400000;
pSmi->MapSize = 0x10000;
break;
}
#ifndef XSERVER_LIBPCIACCESS
pSmi->MapBase = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
memBase, pSmi->MapSize);
#else
{
void **result = (void**)&pSmi->MapBase;
int err = pci_device_map_range(pSmi->PciInfo,
memBase,
pSmi->MapSize,
PCI_DEV_MAP_FLAG_WRITABLE,
result);
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_MapMmio - pci_device_map_range returned %d\n",err);
if (err)
return (FALSE);
}
#endif
if (pSmi->MapBase == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Internal error: could not map "
"MMIO registers.\n");
return (FALSE);
}
switch (pSmi->Chipset) {
case SMI_COUGAR3DR:
pSmi->DPRBase = pSmi->MapBase + 0x000000;
pSmi->VPRBase = pSmi->MapBase + 0x000800;
pSmi->CPRBase = pSmi->MapBase + 0x001000;
pSmi->FPRBase = pSmi->MapBase + 0x005800;
pSmi->IOBase = pSmi->MapBase + 0x0C0000;
pSmi->DataPortBase = pSmi->MapBase + 0x100000;
pSmi->DataPortSize = 0x100000;
break;
case SMI_LYNX3D:
pSmi->DPRBase = pSmi->MapBase + 0x000000;
pSmi->VPRBase = pSmi->MapBase + 0x000800;
pSmi->CPRBase = pSmi->MapBase + 0x001000;
pSmi->IOBase = pSmi->MapBase + 0x040000;
pSmi->DataPortBase = pSmi->MapBase + 0x080000;
pSmi->DataPortSize = 0x100000;
break;
case SMI_LYNXEM:
case SMI_LYNXEMplus:
pSmi->DPRBase = pSmi->MapBase + 0x008000;
pSmi->VPRBase = pSmi->MapBase + 0x00C000;
pSmi->CPRBase = pSmi->MapBase + 0x00E000;
pSmi->IOBase = pSmi->MapBase + 0x300000;
pSmi->DataPortBase = pSmi->MapBase /*+ 0x100000*/;
pSmi->DataPortSize = 0x8000 /*0x200000*/;
break;
case SMI_LYNX3DM:
pSmi->DPRBase = pSmi->MapBase + 0x000000;
pSmi->VPRBase = pSmi->MapBase + 0x000800;
pSmi->CPRBase = pSmi->MapBase + 0x001000;
pSmi->IOBase = pSmi->MapBase + 0x0C0000;
pSmi->DataPortBase = pSmi->MapBase + 0x100000;
pSmi->DataPortSize = 0x100000;
break;
case SMI_MSOC:
pSmi->DPRBase = pSmi->MapBase + 0x100000;
pSmi->VPRBase = pSmi->MapBase + 0x000000;
pSmi->CPRBase = pSmi->MapBase + 0x090000;
pSmi->DCRBase = pSmi->MapBase + 0x080000;
pSmi->SCRBase = pSmi->MapBase + 0x000000;
pSmi->IOBase = 0;
pSmi->DataPortBase = pSmi->MapBase + 0x110000;
pSmi->DataPortSize = 0x10000;
break;
default:
pSmi->DPRBase = pSmi->MapBase + 0x8000;
pSmi->VPRBase = pSmi->MapBase + 0xC000;
pSmi->CPRBase = pSmi->MapBase + 0xE000;
pSmi->IOBase = NULL;
pSmi->DataPortBase = pSmi->MapBase;
pSmi->DataPortSize = 0x8000;
break;
}
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Physical MMIO at 0x%08lX\n", (unsigned long)memBase);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Logical MMIO at %p - %p\n", pSmi->MapBase,
pSmi->MapBase + pSmi->MapSize - 1);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"DPR=%p, VPR=%p, IOBase=%p\n",
pSmi->DPRBase, pSmi->VPRBase, pSmi->IOBase);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"DataPort=%p - %p\n", pSmi->DataPortBase,
pSmi->DataPortBase + pSmi->DataPortSize - 1);
return (TRUE);
}
/* HACK - In some cases the BIOS hasn't filled in the "scratchpad
registers" (SR71) with the right amount of memory installed (e.g. MIPS
platform). Probe it manually. */
static unsigned long
SMI_ProbeMem(ScrnInfoPtr pScrn, unsigned long mem_skip, unsigned long mem_max)
{
SMIPtr pSmi = SMIPTR(pScrn);
unsigned long mem_probe = 1024*1024;
unsigned long aperture_base;
void* mem;
int mr_err;
ENTER();
aperture_base = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM) + mem_skip;
mem_max = min(mem_max , PCI_REGION_SIZE(pSmi->PciInfo, 0) - mem_skip);
#ifndef XSERVER_LIBPCIACCESS
mem = xf86MapPciMem(pScrn->scrnIndex, VIDMEM_MMIO, pSmi->PciTag,
aperture_base, mem_max);
if(!mem)
LEAVE(0);
#else
if((mr_err=pci_device_map_range(pSmi->PciInfo, aperture_base, mem_max,
PCI_DEV_MAP_FLAG_WRITABLE, &mem)))
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_ProbeMem - pci_device_map_range returned %d\n",mr_err);
LEAVE(0);
#endif
while(mem_probe <= mem_max){
MMIO_OUT32(mem, mem_probe-4, 0x55555555);
if(MMIO_IN32(mem, mem_probe-4) != 0x55555555)
break;
MMIO_OUT32(mem, mem_probe-4, 0xAAAAAAAA);
if(MMIO_IN32(mem, mem_probe-4) != 0xAAAAAAAA)
break;
mem_probe <<= 1;
}
#ifndef XSERVER_LIBPCIACCESS
xf86UnMapVidMem(pScrn->scrnIndex, mem, mem_max);
#else
pci_device_unmap_range(pSmi->PciInfo, mem, mem_max);
#endif
LEAVE(mem_probe >> 1);
}
static Bool
SMI_DetectMem(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
MessageType from;
if ((pScrn->videoRam = pScrn->confScreen->device->videoRam)){
pSmi->videoRAMKBytes = pScrn->videoRam;
from = X_CONFIG;
}
else {
unsigned char config;
static int lynx3d_table[4] = { 0, 2, 4, 6 };
static int lynx3dm_table[4] = { 16, 2, 4, 8 };
static int msoc_table[8] = { 4, 8, 16, 32, 64, 2, 0, 0 };
static int default_table[4] = { 1, 2, 4, 0 };
if (IS_MSOC(pSmi)) {
config = (READ_SCR(pSmi, DRAM_CTL) >> 13) & 7;
pSmi->videoRAMKBytes = msoc_table[config] * 1024 -
SHARED_USB_DMA_BUFFER_SIZE;
}
else {
config = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x71);
switch (pSmi->Chipset) {
case SMI_LYNX3D:
pSmi->videoRAMKBytes = lynx3d_table[config >> 6] * 1024 +
512;
break;
case SMI_LYNXEMplus:
pSmi->videoRAMKBytes = SMI_ProbeMem(pScrn, 0, 0x400000) / 1024;
break;
case SMI_LYNX3DM:
pSmi->videoRAMKBytes = lynx3dm_table[config >> 6] * 1024;
break;
case SMI_COUGAR3DR:
/* DANGER - Cougar3DR BIOS is broken - hardcode video ram
* size per instructions from Silicon Motion engineers */
pSmi->videoRAMKBytes = 16 * 1024;
break;
default:
pSmi->videoRAMKBytes = default_table[config >> 6] * 1024;
break;
}
}
from = X_PROBED;
}
pSmi->videoRAMBytes = pSmi->videoRAMKBytes * 1024;
pScrn->videoRam = pSmi->videoRAMKBytes;
xf86DrvMsg(pScrn->scrnIndex, from,
"videoram: %dkB\n", pSmi->videoRAMKBytes);
return (TRUE);
}
Bool
SMI_MapMem(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
vgaHWPtr hwp;
ENTER();
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_MapMem.\n");
if (pSmi->MapBase == NULL && SMI_MapMmio(pScrn) == FALSE)
{
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_MapMem - Immediate Leave.\n");
LEAVE(FALSE);
}
pScrn->memPhysBase = PCI_REGION_BASE(pSmi->PciInfo, 0, REGION_MEM);
if (pSmi->Chipset == SMI_LYNX3DM)
pSmi->fbMapOffset = 0x200000;
else
pSmi->fbMapOffset = 0x0;
#ifndef XSERVER_LIBPCIACCESS
pSmi->FBBase = xf86MapPciMem(pScrn->scrnIndex,
VIDMEM_FRAMEBUFFER,
pSmi->PciTag,
pScrn->memPhysBase + pSmi->fbMapOffset,
pSmi->videoRAMBytes);
#else
{
void **result = (void**)&pSmi->FBBase;
int err = pci_device_map_range(pSmi->PciInfo,
pScrn->memPhysBase +
pSmi->fbMapOffset,
pSmi->videoRAMBytes,
PCI_DEV_MAP_FLAG_WRITABLE |
PCI_DEV_MAP_FLAG_WRITE_COMBINE,
result);
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_MapMem - pci_device_map_range returned %d\n",err);
if (err)
LEAVE(FALSE);
}
#endif
if (pSmi->FBBase == NULL) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Internal error: could not map framebuffer.\n");
LEAVE(FALSE);
}
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Physical frame buffer at 0x%08lX offset: 0x%08lX\n",
pScrn->memPhysBase, (unsigned long)pSmi->fbMapOffset);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Logical frame buffer at %p - %p\n", pSmi->FBBase,
pSmi->FBBase + pSmi->videoRAMBytes - 1);
if (IS_MSOC(pSmi)) {
/* Reserve space for panel cursr, and crt if in dual head mode */
#if SMI_CURSOR_ALPHA_PLANE
pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
(pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_ARGB_CURSOR_SIZE);
#else
pSmi->FBReserved = pSmi->FBCursorOffset = pSmi->videoRAMBytes -
(pSmi->Dualhead ? SMI501_CURSOR_SIZE << 1 : SMI501_CURSOR_SIZE);
# if SMI501_CLI_DEBUG
if (pSmi->useEXA) {
pSmi->batch_active = FALSE;
pSmi->batch_length = 4096;
pSmi->FBReserved -= pSmi->batch_length << 3;
pSmi->batch_offset = pSmi->FBReserved;
pSmi->batch_handle = (int64_t *)(pSmi->FBBase + pSmi->batch_offset);
pSmi->batch_finish = -1;
pSmi->batch_index = 0;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Using command list interpreter debug code\n");
}
# endif
#endif
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_MapMem IS_MSOC: pSmi->FBReserved %lu\n",pSmi->FBReserved);
}
else {
/* Set up offset to hwcursor memory area, at the end of
* the frame buffer.
*/
pSmi->FBCursorOffset = pSmi->videoRAMBytes - SMILYNX_CURSOR_SIZE;
/* set up the fifo reserved space */
if (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x30) & 0x01)/* #1074 */ {
CARD32 fifoOffset = 0;
fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x46) << 3;
fifoOffset |= VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x47) << 11;
fifoOffset |= (VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA,
0x49) & 0x1C) << 17;
pSmi->FBReserved = fifoOffset; /* PDR#1074 */
}
else
pSmi->FBReserved = pSmi->videoRAMBytes - 2048;
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Cursor Offset: %08lX\n",
(unsigned long)pSmi->FBCursorOffset);
/* Assign hwp->MemBase & IOBase here */
hwp = VGAHWPTR(pScrn);
if (pSmi->IOBase != NULL)
vgaHWSetMmioFuncs(hwp, pSmi->MapBase, pSmi->IOBase - pSmi->MapBase);
vgaHWGetIOBase(hwp);
/* Map the VGA memory when the primary video */
if (xf86IsPrimaryPci(pSmi->PciInfo)) {
hwp->MapSize = 0x10000;
if (!vgaHWMapMem(pScrn))
{
xf86DrvMsg(pScrn->scrnIndex, X_DEBUG, "In SMI_MapMem - vgaHWMapMem err\n");
LEAVE(FALSE);
}
pSmi->PrimaryVidMapped = TRUE;
}
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Reserved: %08lX\n",
(unsigned long)pSmi->FBReserved);
LEAVE(TRUE);
}
/* UnMapMem - contains half of pre-4.0 EnterLeave function. The EnterLeave
* function which en/disable access to IO ports and ext. regs
*/
void
SMI_UnmapMem(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
/* Unmap VGA mem if mapped. */
if (pSmi->PrimaryVidMapped) {
vgaHWUnmapMem(pScrn);
pSmi->PrimaryVidMapped = FALSE;
}
SMI_DisableMmio(pScrn);
if (pSmi->MapBase) {
#ifndef XSERVER_LIBPCIACCESS
xf86UnMapVidMem(pScrn->scrnIndex, (pointer)pSmi->MapBase,
pSmi->MapSize);
#else
pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->MapBase,
pSmi->MapSize);
#endif
pSmi->MapBase = NULL;
}
if (pSmi->FBBase) {
#ifndef XSERVER_LIBPCIACCESS
xf86UnMapVidMem(pScrn->scrnIndex, (pointer) pSmi->FBBase,
pSmi->videoRAMBytes);
#else
pci_device_unmap_range(pSmi->PciInfo, (pointer)pSmi->FBBase,
pSmi->videoRAMBytes);
#endif
pSmi->FBBase = NULL;
}
LEAVE();
}
/* This gets called at the start of each server generation. */
static Bool
SMI_ScreenInit(SCREEN_INIT_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
SMIPtr pSmi = SMIPTR(pScrn);
EntityInfoPtr pEnt;
ENTER();
/* Map MMIO regs and framebuffer */
if (!SMI_MapMem(pScrn))
LEAVE(FALSE);
pEnt = xf86GetEntityInfo(pScrn->entityList[0]);
if (!pSmi->pInt10 && pSmi->useBIOS) {
pSmi->pInt10 = xf86InitInt10(pEnt->index);
}
if (!pSmi->pVbe && pSmi->pInt10 && xf86LoaderCheckSymbol("VBEInit")) {
pSmi->pVbe = VBEInit(pSmi->pInt10, pEnt->index);
}
/* Save the chip/graphics state */
pSmi->Save(pScrn);
/* Fill in some needed pScrn fields */
pScrn->vtSema = TRUE;
pScrn->pScreen = pScreen;
pScrn->displayWidth = ((pScrn->virtualX * pSmi->Bpp + 15) & ~15) / pSmi->Bpp;
pSmi->fbArea = NULL;
pSmi->FBOffset = 0;
pScrn->fbOffset = pSmi->FBOffset + pSmi->fbMapOffset;
/* Clear frame buffer */
memset(pSmi->FBBase, 0, pSmi->videoRAMBytes);
/*
* The next step is to setup the screen's visuals, and initialise the
* framebuffer code. In cases where the framebuffer's default choises for
* things like visual layouts and bits per RGB are OK, this may be as simple
* as calling the framebuffer's ScreenInit() function. If not, the visuals
* will need to be setup before calling a fb ScreenInit() function and fixed
* up after.
*/
/*
* Reset the visual list.
*/
miClearVisualTypes();
/* Setup the visuals we support. */
if (!miSetVisualTypes(pScrn->depth, miGetDefaultVisualMask(pScrn->depth),
pScrn->rgbBits, pScrn->defaultVisual))
LEAVE(FALSE);
if (!miSetPixmapDepths ())
LEAVE(FALSE);
/*
* Call the framebuffer layer's ScreenInit function
*/
DEBUG("\tInitializing FB @ 0x%08X for %dx%d (%d)\n",
pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth);
if(!fbScreenInit(pScreen, pSmi->FBBase, pScrn->virtualX, pScrn->virtualY, pScrn->xDpi,
pScrn->yDpi, pScrn->displayWidth, pScrn->bitsPerPixel))
LEAVE(FALSE);
xf86SetBlackWhitePixels(pScreen);
if (pScrn->bitsPerPixel > 8) {
VisualPtr visual;
/* Fixup RGB ordering */
visual = pScreen->visuals + pScreen->numVisuals;
while (--visual >= pScreen->visuals) {
if ((visual->class | DynamicClass) == DirectColor) {
visual->offsetRed = pScrn->offset.red;
visual->offsetGreen = pScrn->offset.green;
visual->offsetBlue = pScrn->offset.blue;
visual->redMask = pScrn->mask.red;
visual->greenMask = pScrn->mask.green;
visual->blueMask = pScrn->mask.blue;
}
}
}
/* must be after RGB ordering fixed */
fbPictureInit(pScreen, 0, 0);
/* Do the CRTC independent initialization */
if(!SMI_HWInit(pScrn))
LEAVE(FALSE);
/* Unless using EXA, regardless or using XAA or not, needs offscreen
* management at least for video. */
if (pSmi->NoAccel || !pSmi->useEXA) {
int numLines;
BoxRec AvailFBArea;
numLines = pSmi->FBReserved / (pScrn->displayWidth * pSmi->Bpp);
AvailFBArea.x1 = 0;
AvailFBArea.y1 = 0;
AvailFBArea.x2 = pScrn->virtualX;
AvailFBArea.y2 = numLines;
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"FrameBuffer Box: %d,%d - %d,%d\n",
AvailFBArea.x1, AvailFBArea.y1, AvailFBArea.x2,
AvailFBArea.y2);
xf86InitFBManager(pScreen, &AvailFBArea);
}
/* Initialize acceleration layer */
if (!pSmi->NoAccel) {
if (pSmi->useEXA && !SMI_EXAInit(pScreen))
LEAVE(FALSE);
else if (!pSmi->useEXA && !SMI_XAAInit(pScreen))
LEAVE(FALSE);
}
/* Initialize the chosen modes */
if (!xf86SetDesiredModes(pScrn))
LEAVE(FALSE);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"Done writing mode. Register dump:\n");
SMI_PrintRegs(pScrn);
#ifdef HAVE_XMODES
xf86DiDGAInit(pScreen, (unsigned long)(pSmi->FBBase + pScrn->fbOffset));
#endif
/* Initialise cursor functions */
miDCInitialize(pScreen, xf86GetPointerScreenFuncs());
/* Initialize HW cursor layer. Must follow software cursor
* initialization.
*/
if (pSmi->HwCursor) {
int size, flags;
if (IS_MSOC(pSmi)) {
size = SMI501_MAX_CURSOR;
flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK);
#if SMI_CURSOR_ALPHA_PLANE
if (!pSmi->Dualhead)
flags |= HARDWARE_CURSOR_ARGB;
#endif
}
else {
size = SMILYNX_MAX_CURSOR;
flags = (HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8 |
HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK |
HARDWARE_CURSOR_AND_SOURCE_WITH_MASK |
HARDWARE_CURSOR_BIT_ORDER_MSBFIRST |
HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
HARDWARE_CURSOR_INVERT_MASK);
}
if (!xf86_cursors_init(pScreen, size, size, flags))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Hardware cursor initialization failed\n");
}
if(!xf86CrtcScreenInit(pScreen))
LEAVE(FALSE);
/* Initialise default colormap */
if (!miCreateDefColormap(pScreen))
LEAVE(FALSE);
/* Initialize colormap layer. Must follow initialization of the default
* colormap. And SetGamma call, else it will load palette with solid white.
*/
if (!xf86HandleColormaps(pScreen, 256, pScrn->rgbBits,SMI_LoadPalette, NULL,
CMAP_RELOAD_ON_MODE_SWITCH | CMAP_PALETTED_TRUECOLOR))
LEAVE(FALSE);
pScreen->SaveScreen = SMI_SaveScreen;
pSmi->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = SMI_CloseScreen;
if ((IS_MSOC(pSmi) &&
!xf86DPMSInit(pScreen, SMI501_DisplayPowerManagementSet, 0)) ||
(!IS_MSOC(pSmi) &&
!xf86DPMSInit(pScreen, SMILynx_DisplayPowerManagementSet, 0)))
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "DPMS initialization failed!\n");
SMI_InitVideo(pScreen);
/* Report any unused options (only for the first generation) */
if (serverGeneration == 1) {
xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);
}
LEAVE(TRUE);
}
/*
* This is called at the end of each server generation. It restores the
* original (text) mode. It should also unmap the video memory, and free any
* per-generation data allocated by the driver. It should finish by unwrapping
* and calling the saved CloseScreen function.
*/
static Bool
SMI_CloseScreen(CLOSE_SCREEN_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
SMIPtr pSmi = SMIPTR(pScrn);
Bool ret;
ENTER();
if (pSmi->HwCursor)
xf86_cursors_fini(pScreen);
if (pScrn->vtSema)
/* Restore console mode and unmap framebuffer */
SMI_LeaveVT(VT_FUNC_ARGS);
#ifdef HAVE_XAA_H
if (pSmi->XAAInfoRec != NULL) {
XAADestroyInfoRec(pSmi->XAAInfoRec);
}
#endif
if (pSmi->EXADriverPtr) {
exaDriverFini(pScreen);
pSmi->EXADriverPtr = NULL;
}
if (pSmi->pVbe != NULL) {
vbeFree(pSmi->pVbe);
pSmi->pVbe = NULL;
}
if (pSmi->pInt10 != NULL) {
xf86FreeInt10(pSmi->pInt10);
pSmi->pInt10 = NULL;
}
if (pSmi->ptrAdaptor != NULL) {
free(pSmi->ptrAdaptor);
}
if (pSmi->BlockHandler != NULL) {
pScreen->BlockHandler = pSmi->BlockHandler;
}
pScrn->vtSema = FALSE;
pScreen->CloseScreen = pSmi->CloseScreen;
ret = (*pScreen->CloseScreen)(CLOSE_SCREEN_ARGS);
LEAVE(ret);
}
static void
SMI_FreeScreen(FREE_SCREEN_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
SMI_FreeRec(pScrn);
}
static Bool
SMI_SaveScreen(ScreenPtr pScreen, int mode)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
ENTER();
if(xf86IsUnblank(mode)){
pScrn->DPMSSet(pScrn, DPMSModeOn, 0);
}else{
pScrn->DPMSSet(pScrn, DPMSModeOff, 0);
}
LEAVE(TRUE);
}
void
SMI_AdjustFrame(ADJUST_FRAME_ARGS_DECL)
{
SCRN_INFO_PTR(arg);
xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
xf86CrtcPtr compat_crtc = crtcConf->output[crtcConf->compat_output]->crtc;
ENTER();
SMICRTC(compat_crtc)->adjust_frame(compat_crtc,x,y);
LEAVE();
}
Bool
SMI_SwitchMode(SWITCH_MODE_ARGS_DECL)
{
Bool ret;
SCRN_INFO_PTR(arg);
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
ret = xf86SetSingleMode(pScrn, mode, RR_Rotate_0);
if (!pSmi->NoAccel)
SMI_EngineReset(pScrn);
LEAVE(ret);
}
void
SMI_LoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies,
LOCO *colors, VisualPtr pVisual)
{
xf86CrtcConfigPtr crtcConf = XF86_CRTC_CONFIG_PTR(pScrn);
int crtc_idx,i,j;
ENTER();
if(pScrn->bitsPerPixel == 16){
/* Expand the RGB 565 palette into the 256-elements LUT */
for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
for(i=0; i<numColors; i++){
int idx = indicies[i];
if(idx<32){
for(j=0; j<8; j++){
crtcPriv->lut_r[idx*8 + j] = colors[idx].red << 8;
crtcPriv->lut_b[idx*8 + j] = colors[idx].blue << 8;
}
}
for(j=0; j<4; j++)
crtcPriv->lut_g[idx*4 + j] = colors[idx].green << 8;
}
crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
}
}else{
for(crtc_idx=0; crtc_idx<crtcConf->num_crtc; crtc_idx++){
SMICrtcPrivatePtr crtcPriv = SMICRTC(crtcConf->crtc[crtc_idx]);
for(i = 0; i < numColors; i++) {
int idx = indicies[i];
crtcPriv->lut_r[idx] = colors[idx].red << 8;
crtcPriv->lut_g[idx] = colors[idx].green << 8;
crtcPriv->lut_b[idx] = colors[idx].blue << 8;
}
crtcPriv->load_lut(crtcConf->crtc[crtc_idx]);
}
}
LEAVE();
}
static void
SMI_DisableVideo(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
CARD8 tmp;
if (!IS_MSOC(pSmi)) {
if (!(tmp = VGAIN8(pSmi, VGA_DAC_MASK)))
return;
pSmi->DACmask = tmp;
VGAOUT8(pSmi, VGA_DAC_MASK, 0);
}
}
static void
SMI_EnableVideo(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
if (!IS_MSOC(pSmi)) {
VGAOUT8(pSmi, VGA_DAC_MASK, pSmi->DACmask);
}
}
void
SMI_EnableMmio(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
if (!IS_MSOC(pSmi)) {
vgaHWPtr hwp = VGAHWPTR(pScrn);
CARD8 tmp;
/*
* Enable chipset (seen on uninitialized secondary cards) might not be
* needed once we use the VGA softbooter
*/
vgaHWSetStdFuncs(hwp);
/* Enable linear mode */
tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18);
pSmi->SR18Value = tmp; /* PDR#521 */
VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, tmp | 0x11);
/* Enable 2D/3D Engine and Video Processor */
tmp = VGAIN8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21);
pSmi->SR21Value = tmp; /* PDR#521 */
VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, tmp & ~0x03);
}
LEAVE();
}
void
SMI_DisableMmio(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
if (!IS_MSOC(pSmi)) {
vgaHWPtr hwp = VGAHWPTR(pScrn);
vgaHWSetStdFuncs(hwp);
/* Disable 2D/3D Engine and Video Processor */
VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x21, pSmi->SR21Value); /* PDR#521 */
/* Disable linear mode */
VGAOUT8_INDEX(pSmi, VGA_SEQ_INDEX, VGA_SEQ_DATA, 0x18, pSmi->SR18Value); /* PDR#521 */
}
LEAVE();
}
static void
SMI_ProbeDDC(ScrnInfoPtr pScrn, int index)
{
vbeInfoPtr pVbe;
if (xf86LoadSubModule(pScrn, "vbe")) {
pVbe = VBEInit(NULL, index);
ConfiguredMonitor = vbeDoEDID(pVbe, NULL);
vbeFree(pVbe);
}
}
static Bool
SMI_HWInit(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
ENTER();
if(IS_MSOC(pSmi))
LEAVE(SMI501_HWInit(pScrn));
else
LEAVE(SMILynx_HWInit(pScrn));
}
void
SMI_PrintRegs(ScrnInfoPtr pScrn)
{
SMIPtr pSmi = SMIPTR(pScrn);
int i;
ENTER();
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"START register dump ------------------\n");
if(IS_MSOC(pSmi))
SMI501_PrintRegs(pScrn);
else
SMILynx_PrintRegs(pScrn);
xf86ErrorFVerb(VERBLEV, "\n\nDPR x0 x4 x8 xC");
for (i = 0x00; i <= 0x44; i += 4) {
if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_DPR(pSmi, i));
}
xf86ErrorFVerb(VERBLEV, "\n\nVPR x0 x4 x8 xC");
for (i = 0x00; i <= 0x60; i += 4) {
if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_VPR(pSmi, i));
}
xf86ErrorFVerb(VERBLEV, "\n\nCPR x0 x4 x8 xC");
for (i = 0x00; i <= 0x18; i += 4) {
if ((i & 0xF) == 0x0) xf86ErrorFVerb(VERBLEV, "\n%02X|", i);
xf86ErrorFVerb(VERBLEV, " %08lX", (unsigned long)READ_CPR(pSmi, i));
}
xf86ErrorFVerb(VERBLEV, "\n\n");
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, VERBLEV,
"END register dump --------------------\n");
LEAVE();
}
[ 1534.937]
X.Org X Server 1.20.4
X Protocol Version 11, Revision 0
[ 1535.015] Build Operating System: Linux 4.19.0-10-amd64 i686 Debian
[ 1535.043] Current Operating System: Linux cypress 4.19.0-12-686-pae #1 SMP Debian 4.19.152-1 (2020-10-18) i686
[ 1535.043] Kernel command line: BOOT_IMAGE=/boot/vmlinuz-4.19.0-12-686-pae root=UUID=824e304b-56a0-4892-9672-b1e03a77a125 ro quiet
[ 1535.102] Build Date: 27 August 2020 08:51:48AM
[ 1535.131] xorg-server 2:1.20.4-1+deb10u1 (https://www.debian.org/support)
[ 1535.161] Current version of pixman: 0.36.0
[ 1535.220] Before reporting problems, check http://wiki.x.org
to make sure that you have the latest version.
[ 1535.220] Markers: (--) probed, (**) from config file, (==) default setting,
(++) from command line, (!!) notice, (II) informational,
(WW) warning, (EE) error, (NI) not implemented, (??) unknown.
[ 1535.340] (==) Log file: "/var/log/Xorg.0.log", Time: Mon Nov 16 00:33:36 2020
[ 1535.389] (==) Using system config directory "/usr/share/X11/xorg.conf.d"
[ 1535.391] (==) No Layout section. Using the first Screen section.
[ 1535.391] (==) No screen section available. Using defaults.
[ 1535.392] (**) |-->Screen "Default Screen Section" (0)
[ 1535.392] (**) | |-->Monitor "<default monitor>"
[ 1535.394] (==) No monitor specified for screen "Default Screen Section".
Using a default monitor configuration.
[ 1535.394] (==) Automatically adding devices
[ 1535.394] (==) Automatically enabling devices
[ 1535.394] (==) Automatically adding GPU devices
[ 1535.394] (==) Max clients allowed: 256, resource mask: 0x1fffff
[ 1535.394] (WW) The directory "/usr/share/fonts/X11/cyrillic" does not exist.
[ 1535.394] Entry deleted from font path.
[ 1535.395] (==) FontPath set to:
/usr/share/fonts/X11/misc,
/usr/share/fonts/X11/100dpi/:unscaled,
/usr/share/fonts/X11/75dpi/:unscaled,
/usr/share/fonts/X11/Type1,
/usr/share/fonts/X11/100dpi,
/usr/share/fonts/X11/75dpi,
built-ins
[ 1535.395] (==) ModulePath set to "/usr/lib/xorg/modules"
[ 1535.395] (II) The server relies on udev to provide the list of input devices.
If no devices become available, reconfigure udev or disable AutoAddDevices.
[ 1535.395] (II) Loader magic: 0x6f8740
[ 1535.395] (II) Module ABI versions:
[ 1535.395] X.Org ANSI C Emulation: 0.4
[ 1535.395] X.Org Video Driver: 24.0
[ 1535.395] X.Org XInput driver : 24.1
[ 1535.395] X.Org Server Extension : 10.0
[ 1535.400] (++) using VT number 1
[ 1535.415] (II) systemd-logind: took control of session /org/freedesktop/login1/session/_31
[ 1535.428] (--) PCI:*(1@0:0:0) 126f:0710:107b:2550 rev 163, Mem @ 0xfd000000/16777216, BIOS @ 0x????????/131072
[ 1535.428] (II) LoadModule: "glx"
[ 1535.430] (II) Loading /usr/lib/xorg/modules/extensions/libglx.so
[ 1535.439] (II) Module glx: vendor="X.Org Foundation"
[ 1535.439] compiled for 1.20.4, module version = 1.0.0
[ 1535.440] ABI class: X.Org Server Extension, version 10.0
[ 1535.440] (==) Matched siliconmotion as autoconfigured driver 0
[ 1535.440] (==) Matched modesetting as autoconfigured driver 1
[ 1535.440] (==) Matched fbdev as autoconfigured driver 2
[ 1535.440] (==) Matched vesa as autoconfigured driver 3
[ 1535.440] (==) Assigned the driver to the xf86ConfigLayout
[ 1535.440] (II) LoadModule: "siliconmotion"
[ 1535.441] (II) Loading /usr/lib/xorg/modules/drivers/siliconmotion_drv.so
[ 1535.442] (II) Module siliconmotion: vendor="X.Org Foundation"
[ 1535.442] compiled for 1.20.4, module version = 1.7.9
[ 1535.442] Module class: X.Org Video Driver
[ 1535.442] ABI class: X.Org Video Driver, version 24.0
[ 1535.442] (II) LoadModule: "modesetting"
[ 1535.443] (II) Loading /usr/lib/xorg/modules/drivers/modesetting_drv.so
[ 1535.444] (II) Module modesetting: vendor="X.Org Foundation"
[ 1535.444] compiled for 1.20.4, module version = 1.20.4
[ 1535.444] Module class: X.Org Video Driver
[ 1535.444] ABI class: X.Org Video Driver, version 24.0
[ 1535.445] (II) LoadModule: "fbdev"
[ 1535.445] (II) Loading /usr/lib/xorg/modules/drivers/fbdev_drv.so
[ 1535.446] (II) Module fbdev: vendor="X.Org Foundation"
[ 1535.446] compiled for 1.20.0, module version = 0.5.0
[ 1535.446] Module class: X.Org Video Driver
[ 1535.446] ABI class: X.Org Video Driver, version 24.0
[ 1535.446] (II) LoadModule: "vesa"
[ 1535.447] (II) Loading /usr/lib/xorg/modules/drivers/vesa_drv.so
[ 1535.448] (II) Module vesa: vendor="X.Org Foundation"
[ 1535.448] compiled for 1.20.1, module version = 2.4.0
[ 1535.448] Module class: X.Org Video Driver
[ 1535.448] ABI class: X.Org Video Driver, version 24.0
[ 1535.448] (II) SMI: driver (version 1.7.9) for Silicon Motion Lynx chipsets: Lynx,
LynxE, Lynx3D, LynxEM, LynxEM+, Lynx3DM, Cougar3DR, MSOC
[ 1535.449] (II) modesetting: Driver for Modesetting Kernel Drivers: kms
[ 1535.449] (II) FBDEV: driver for framebuffer: fbdev
[ 1535.449] (II) VESA: driver for VESA chipsets: vesa
[ 1535.450] (WW) Falling back to old probe method for siliconmotion
[ 1535.450] (--) Assigning device section with no busID to primary device
[ 1535.450] (--) Chipset LynxEM found
[ 1535.450] (WW) Falling back to old probe method for modesetting
[ 1535.451] (EE) open /dev/dri/card0: No such file or directory
[ 1535.451] (WW) Falling back to old probe method for fbdev
[ 1535.451] (II) Loading sub module "fbdevhw"
[ 1535.451] (II) LoadModule: "fbdevhw"
[ 1535.452] (II) Loading /usr/lib/xorg/modules/libfbdevhw.so
[ 1535.472] (II) Module fbdevhw: vendor="X.Org Foundation"
[ 1535.472] compiled for 1.20.4, module version = 0.0.2
[ 1535.473] ABI class: X.Org Video Driver, version 24.0
[ 1535.473] (II) Loading sub module "vgahw"
[ 1535.473] (II) LoadModule: "vgahw"
[ 1535.474] (II) Loading /usr/lib/xorg/modules/libvgahw.so
[ 1535.489] (II) Module vgahw: vendor="X.Org Foundation"
[ 1535.489] compiled for 1.20.4, module version = 0.1.0
[ 1535.489] ABI class: X.Org Video Driver, version 24.0
[ 1535.490] (II) SMI(0): Creating default Display subsection in Screen section
"Default Screen Section" for depth/fbbpp 24/32
[ 1535.490] (==) SMI(0): Depth 24, (--) framebuffer bpp 32
[ 1535.491] (==) SMI(0): RGB weight 888
[ 1535.491] (==) SMI(0): Default visual is TrueColor
[ 1535.491] (==) SMI(0): PCI Burst enabled
[ 1535.491] (==) SMI(0): PCI Retry enabled
[ 1535.491] (==) SMI(0): Using Hardware Cursor
[ 1535.491] (II) Loading sub module "int10"
[ 1535.491] (II) LoadModule: "int10"
[ 1535.492] (II) Loading /usr/lib/xorg/modules/libint10.so
[ 1535.533] (II) Module int10: vendor="X.Org Foundation"
[ 1535.533] compiled for 1.20.4, module version = 1.0.0
[ 1535.533] ABI class: X.Org Video Driver, version 24.0
[ 1535.539] (II) SMI(0): Primary V_BIOS segment is: 0xc000
[ 1535.540] (II) Loading sub module "vbe"
[ 1535.540] (II) LoadModule: "vbe"
[ 1535.540] (II) Loading /usr/lib/xorg/modules/libvbe.so
[ 1535.570] (II) Module vbe: vendor="X.Org Foundation"
[ 1535.571] compiled for 1.20.4, module version = 1.1.0
[ 1535.571] ABI class: X.Org Video Driver, version 24.0
[ 1535.902] (II) SMI(0): VESA BIOS not detected
[ 1535.903] (WW) SMI(0): VBE initialization failed: falling back to UseBIOS disabled.
[ 1535.903] (--) SMI(0): Chipset: "LynxEM"
[ 1535.903] (==) SMI(0): Dual head disabled
[ 1535.903] (==) SMI(0): Using XAA acceleration architecture
[ 1535.903] (DB) SMI(0): In SMI_MapMmio - pci_device_map_range returned 22
[ 1535.903] (--) SMI(0): videoram: 4096kB
[ 1535.904] (DB) SMI(0): In SMI_MapMem.
[ 1535.904] (DB) SMI(0): In SMI_MapMmio - pci_device_map_range returned 22
[ 1535.904] (DB) SMI(0): In SMI_MapMem - Immediate Leave.
[ 1535.904] (II) SMI(0): TFT Panel Size = 1024x768
[ 1535.904] (II) Loading sub module "i2c"
[ 1535.904] (II) LoadModule: "i2c"
[ 1535.904] (II) Module "i2c" already built-in
[ 1535.904] (II) SMI(0): I2C bus "I2C bus" initialized.
[ 1535.904] (II) Loading sub module "ddc"
[ 1535.905] (II) LoadModule: "ddc"
[ 1535.905] (II) Module "ddc" already built-in
[ 1535.905] (==) SMI(0): Using gamma correction (1.0, 1.0, 1.0)
[ 1535.905] (II) SMI(0): MCLK = 85.909
[ 1535.905] (II) SMI(0): Output LVDS has no monitor section
[ 1535.905] (II) SMI(0): Printing probed modes for output LVDS
[ 1535.905] (II) SMI(0): Modeline "1024x768"x59.9 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync (47.8 kHz)
[ 1535.905] (II) SMI(0): Output LVDS connected
[ 1535.905] (II) SMI(0): Using exact sizes for initial modes
[ 1535.906] (II) SMI(0): Output LVDS using initial mode 1024x768 +0+0
[ 1535.906] (DB) SMI(0): pSmi->Bpp 4
[ 1535.906] (DB) SMI(0): aligned_pitch 4096
[ 1535.906] (DB) SMI(0): In SMI_PreInit: pSmi->FBReserved 0
[ 1535.906] (EE) SMI(0): Not enough video memory for the configured screen size (1024x1024) and color depth.
[ 1535.906] (II) UnloadModule: "siliconmotion"
[ 1535.906] (II) UnloadSubModule: "vbe"
[ 1535.906] (II) Unloading vbe
[ 1535.907] (II) UnloadSubModule: "int10"
[ 1535.907] (II) Unloading int10
[ 1535.907] (II) UnloadSubModule: "vgahw"
[ 1535.907] (II) Unloading vgahw
[ 1535.907] (EE) Screen(s) found, but none have a usable configuration.
[ 1535.907] (EE)
Fatal server error:
[ 1535.908] (EE) no screens found(EE)
[ 1535.908] (EE)
Please consult the The X.Org Foundation support
at http://wiki.x.org
for help.
[ 1535.908] (EE) Please also check the log file at "/var/log/Xorg.0.log" for additional information.
[ 1535.908] (EE)
[ 1535.980] (EE) Server terminated with error (1). Closing log file.
Reply to: