📄 smi.cpp
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1997-2000 Microsoft and/or its suppliers. All rights reserved.
Copyright (c) 2002 Silicon Motion, Inc.
Module Name: smi.cpp
Abstract: Main initialization and display set-modes codes
Notes:
--*/
#include "precomp.h"
#ifdef SMI_LINEARPATCH
#include <wdm.h>
#endif
#include "bootarg.h"
#ifdef HOST_ENABLE
#ifdef XSCALE
#include <xsc1.h>
#include <gpio.h>
#include <lcd.h>
#ifdef UMA
#include <memdefs.h>
#endif
#endif
#endif
// Specify all the required functions and variables for WinCE 3.00 and 4.00 compability
#if (_WINCEOSVER == 300) // For CE 300--
// Create own palette entries
#include "palette.h"
INSTANTIATE_PALETTE
#define MONITORS_MAX 1
class GPE* (*pfnGetGPEPerCard)(int);
#else // For CE400++
// Use system palette entries, 8Bpp we use the natural palette
#include <syspal.h>
#endif
// DEBUG ZONE definition (found in GPE.H)
// #define GPE_ZONE_ERROR DEBUGZONE(0) = 0x0001
// #define GPE_ZONE_WARNING DEBUGZONE(1) = 0x0002
// #define GPE_ZONE_PERF DEBUGZONE(2) = 0x0004
// #define GPE_ZONE_TEMP DEBUGZONE(3) = 0x0008
//
// #define GPE_ZONE_ENTER DEBUGZONE(4) = 0x0010
// #define GPE_ZONE_INIT DEBUGZONE(5) = 0x0020
// #define GPE_ZONE_BLT_HI DEBUGZONE(6) = 0x0040
// #define GPE_ZONE_BLT_LO DEBUGZONE(7) = 0x0080
//
// #define GPE_ZONE_CREATE DEBUGZONE(8) = 0x0100
// #define GPE_ZONE_FLIP DEBUGZONE(9) = 0x0200
// #define GPE_ZONE_LINE DEBUGZONE(10) = 0x0400
// #define GPE_ZONE_HW DEBUGZONE(11) = 0x0800
//
// #define GPE_ZONE_POLY DEBUGZONE(12) = 0x1000
// #define GPE_ZONE_CURSOR DEBUGZONE(13) = 0x2000
// #define GPE_ZONE_ DEBUGZONE(14) = 0x4000
// #define GPE_ZONE_ DEBUGZONE(15) = 0x8000
// Start with Errors, warnings, and init messages
INSTANTIATE_GPE_ZONES(0x0023, "SMI Driver", "unused1", "unused2")
// Specify all macros here
#define DRIVER_REGISTRY_STRING TEXT("Drivers\\Display\\SMIVGX")
#define DRIVER_MULTIMON_REGISTRY_STRING TEXT("Drivers\\Display\\SMIVGX\\MONITOR")
#define MONITOR_REGISTRY_STRING TEXT("SYSTEM\\GDI\\MONITORS")
#define dim(x) (sizeof(x) / sizeof(x[0]))
// Macro for printing debug messages
#if 1
// Print messages only in DEBUG mode
#define MESSAGE DEBUGMSG
#define MESSAGE_ZONE GPE_ZONE_WARNING
#else
// Force messages even in RELEASE mode
#define MESSAGE RETAILMSG
#define MESSAGE_ZONE 0
#endif
// Specify all global variables here
#ifdef DD_ENABLE
static DDGPE *pGPE = (DDGPE *)NULL;
#else // ! DD_ENABLE
static GPE *pGPE = (GPE *)NULL;
#endif // DD_ENABLE
static SMI *pSMI[MONITORS_MAX]={NULL};
static DWORD g_dwMonitorsExpected=1;
static SMISETTINGS g_DefaultSettings;
static TCHAR g_szBaseInstance[256];
PUCHAR g_pREG;
BOOL g_bSaveSurface = FALSE;
#ifdef ENABLE_DIRECT3D
SMI* ppdev = (SMI*)NULL;
_SMDMA gblSMDMA; //_SMDMA defined in smdma.h
#endif // ENABLE_DIRECT3D
// Specify all global functions here
// This prototype avoids problems exporting from .lib
BOOL APIENTRY GPEEnableDriver(ULONG iEngineVersion, ULONG cj, DRVENABLEDATA *pded, PENGCALLBACKS pEngCallbacks);
GPE *GetGPEPerCard(int iCard);
#if (_WINCEOSVER==420)
int (__cdecl* pfnDrvGradientFill)(struct _SURFOBJ *,struct _CLIPOBJ *,struct _XLATEOBJ *,struct _TRIVERTEX *,
unsigned long,void *,unsigned long,struct _RECTL *,struct _POINTL *,unsigned long) = NULL;
#endif
// DisplayInit
//
// GWES will invoke this routine once prior to making any other calls into the driver.
// This routine needs to save its instance path information and return TRUE. If it
// returns FALSE, GWES will abort the display initialization.
//
// Inputs: pszInstance = Instance name of SMI driver
// g_dwNumMonitors = Number of monitors expected to be supported
//
// Returns: See description above
//
BOOL APIENTRY DisplayInit(LPCTSTR pszInstance, DWORD dwNumMonitors)
{
DEBUGMSG(GPE_ZONE_INIT, (TEXT("SMI: Display instance '%s', Num monitors = %d\r\n"),
pszInstance != NULL ? pszInstance : TEXT("<NULL>"), dwNumMonitors));
// if we expect to be a PCI device, then there must be an instance
if(pszInstance != NULL)
{
// save our first instance path (without instance specifier) along with
// the number of monitors we expect to support
_tcsncpy(g_szBaseInstance, pszInstance, dim(g_szBaseInstance));
//g_szBaseInstance[_tcslen(g_szBaseInstance) - 1] = 0;
}
else
{
g_szBaseInstance[0] = 0;
}
g_dwMonitorsExpected = dwNumMonitors;
return TRUE;
}
//
// DrvEnableDriver
//
// This function sets up the main entry point of the GPE compliant Display Driver.
// GetGPE and GetGPEPerCard
//
BOOL APIENTRY DrvEnableDriver(ULONG iEngineVersion, ULONG cj, DRVENABLEDATA *pded, PENGCALLBACKS pEngCallbacks)
{
pfnGetGPEPerCard = GetGPEPerCard;
return GPEEnableDriver(iEngineVersion, cj, pded, pEngCallbacks);
}
//
// VirtualAddress
//
// Translate and convert a physical address range into a virtual address range.
// NOTE: This is probably where most platform compability needs to be addressed
// eg. Certain platform may not support MMMapIoSpace, they may instead
// need VirtualAlloc, VirtualCopy combination.
// OR. They may not support HalTranslateBusAddress, thus need to
// use other functions.
//
// Inputs: StartAddress = PCI Address of the hardware
// Length = Size of the memory space required
//
// Returns: Accessible virtual address of StartAddress
//
PUCHAR VirtualAddress(ULONG StartAddress, ULONG Length)
{
#ifndef HOST_ENABLE
ULONG inIoSpace;
#endif
PHYSICAL_ADDRESS ioPhysicalBase;
PUCHAR pjAddress;
#if 0 // Enable this section of the code for certain platforms, as necessary
// Some platform may not need this part...
#else
// Do translate to System address
#ifndef HOST_ENABLE
inIoSpace = 0;
#endif
ioPhysicalBase.HighPart = 0;
ioPhysicalBase.LowPart = StartAddress;
#ifndef HOST_ENABLE
if (!HalTranslateBusAddress(PCIBus, 0, ioPhysicalBase,
&inIoSpace,&ioPhysicalBase)
)
{
return(NULL);
}
#endif
#endif
#if 0//defined(XSCALE) // Enable this section of the code for certain platforms, as necessary
// Allocate a pointer that holds the virtual address.
pjAddress = (PUCHAR) VirtualAlloc(0, Length, MEM_RESERVE, PAGE_NOACCESS);
if (pjAddress == NULL)
return(NULL);
// (ioPhysicalBase.LowPart >> 8) because of PAGE_PHYSICAL flag
if (!VirtualCopy((PVOID) pjAddress, (PVOID) (ioPhysicalBase.LowPart >> 8), Length,
PAGE_READWRITE | PAGE_NOCACHE | PAGE_PHYSICAL))
{
VirtualFree((PVOID)pjAddress, 0, MEM_RELEASE);
return(NULL);
}
#else
pjAddress = (UCHAR*) MmMapIoSpace(ioPhysicalBase, Length, FALSE);
#endif
return(pjAddress);
}
BOOL UnMapMemory(PVOID pVirtualAddress, DWORD SourceSize)
{
BOOL bSuccess = TRUE;
if (!VirtualFree(pVirtualAddress, SourceSize,MEM_DECOMMIT))
{
RETAILMSG(1, (TEXT("ERROR! Unable to decommit memory 0x%08X!\r\n"), pVirtualAddress));
bSuccess = FALSE;
}
if (!VirtualFree(pVirtualAddress, 0,MEM_RELEASE))
{
RETAILMSG(1, (TEXT("ERROR! Unable to release memory 0x%08X!\r\n"), pVirtualAddress));
bSuccess = FALSE;
}
return bSuccess;
}
//
// DetectCard
// Detects an SMI card and allocate virtual memory for the Framebuffer Base Address
// and Register Base Address video card
// Inputs: nMonitorNo = Current monitor number
// pss = Pointer to the SMISETTINGS
//
// Outputs: pss = Contains video card hardware info (Base Addresses,
// Int, Chip ID)
//
// Returns: Boolean on whether or not an SMI card is found
//
BOOL DetectCard(int nMonitorNo, SMISETTINGS *pss)
{
// For All Different Platforms Detection
#ifdef PLATFORM_WCEFA //For Automotive based detection
#elif defined(PLATFORM_WCE400PCI) // For special WindowsCE 400 based PCI detection
HKEY hkInstance;
DDKWINDOWINFO dwi;
DDKPCIINFO dpi;
TCHAR szInstance[256];
// read the registry to get our PCI instance information
wsprintf(szInstance, _T("%s%u"), g_szBaseInstance, nMonitorNo + 1);
dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, szInstance, 0, 0, &hkInstance);
if (dwStatus == ERROR_SUCCESS) {
dwi.cbSize = sizeof(dwi);
dwStatus = DDKReg_GetWindowInfo(hkInstance, &dwi);
if (dwStatus == ERROR_SUCCESS) {
dpi.cbSize = sizeof(dpi);
dwStatus = DDKReg_GetPciInfo(hkInstance, &dpi);
}
RegCloseKey(hkInstance);
}
// check the registry information
if (dwStatus == ERROR_SUCCESS)
{
if ((dpi.dwWhichIds &
(PCIIDM_VENDORID | PCIIDM_CLASS | PCIIDM_SUBCLASS)) != (PCIIDM_VENDORID | PCIIDM_CLASS | PCIIDM_SUBCLASS)
)
{
dwStatus = ERROR_INVALID_DATA;
}
else if (dpi.idVals[PCIID_VENDORID] != PCI_VENDOR_SMI ||
dpi.idVals[PCIID_CLASS] != PCI_CLASS_DISPLAY ||
(dpi.idVals[PCIID_SUBCLASS] != PCI_SUBCLASS_DISPLAY && dpi.idVals[PCIID_SUBCLASS] != 0x80)
)
{
dwStatus = ERROR_INVALID_DATA;
}
else if (dwi.dwNumMemWindows != 2)
{
dwStatus = ERROR_INVALID_DATA;
}
}
// did we find the device?
if (dwStatus != ERROR_SUCCESS)
{
// Couldn't find an SMI card, what to do now?
RETAILMSG (1, ((L"SMI card instance %d not found at '%s'\r\n"), nMonitorNo + 1, szInstance));
bRet = FALSE;
}
else
{
TCHAR szResolution[16],szResString[16];
PCI_SLOT_NUMBER slotNumber;
PCI_COMMON_CONFIG pciConfig;
USHORT newCommand;
int length;
// make sure the card is enabled -- some platforms may only enable one video card
slotNumber.u.AsULONG = 0;
slotNumber.u.bits.DeviceNumber = dpi.dwDeviceNumber;
slotNumber.u.bits.FunctionNumber = dpi.dwFunctionNumber;
length = HalGetBusData(PCIConfiguration, dwi.dwBusNumber, slotNumber.u.AsULONG,
&pciConfig, sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific));
if (length == 0 || pciConfig.VendorID == 0xFFFF)
{
dwStatus = ERROR_GEN_FAILURE;
bRet = FALSE;
}
else
{
newCommand = pciConfig.Command | 0x07;
HalSetBusDataByOffset (PCIConfiguration, dwi.dwBusNumber, slotNumber.u.AsULONG, &newCommand, 0x04, 0x02);
}
}
return (bRet);
#elif defined(HOST_ENABLE)
// Add by John Huang *********************************************
#if defined(XSCALE)
{
#if defined (ACCELENT)
volatile PUCHAR pBuf, pBuf2;
PGPIO_REGS pGpio;
PMEMC pMemController;
SA2lcdregs *pLCDController;
pMemController= (PMEMC)VirtualAddress(MEMC_BASE_PHYSICAL, sizeof(MEMC_STRUCT));
pBuf = (volatile PUCHAR) pMemController;
if (pBuf == NULL) return (FALSE);
pMemController->msc1 &= 0xffff0000;
pMemController->msc1 |= 0x00009204; // 0x00009234
pMemController->mdrefr |= 0x01010000; // Set free running clock and SDCLK[1] to 100MHz
// pMemController->mdrefr |= 0x01030000; // Bit:17 1 Set SDCLK[1] to 50MHz
UnMapMemory(pBuf, sizeof(MEMC_STRUCT));
pLCDController= (SA2lcdregs *)VirtualAddress(LCD_BASE_PHYSICAL, sizeof(SA2lcdregs));
pBuf = (volatile PUCHAR) pLCDController;
if (pBuf == NULL) return (FALSE);
pLCDController->LCCR0 |= LCD_DIS; // BIT:10 DISABLE lcd CONTROLLER
RETAILMSG(1, (TEXT("LCCR0 value -> 0x%08X\r\n"), pLCDController->LCCR0));
UnMapMemory(pBuf, sizeof(SA2lcdregs));
RETAILMSG(1,(TEXT("\r\n- GPIO\r\n")));
pGpio = (PGPIO_REGS) VirtualAddress(0x40E00000, sizeof(GPIO_REGS));
pBuf2 = (volatile PUCHAR)pGpio;
if (pBuf2 == NULL) return (FALSE);
pGpio->GAFR0_z = (pGpio->GAFR0_z & ~0x30000000) | 0x20000000;
pGpio->GAFR1_x = (pGpio->GAFR1_x & ~0x30) | 0x10;
pGpio->GAFR1_y = (pGpio->GAFR1_y & ~0xf) | 0xa;
UnMapMemory(pBuf2, sizeof(GPIO_REGS));
RETAILMSG(1,(TEXT("\r\n- Voyager\r\n")));
pBuf2 = (volatile PUCHAR)VirtualAddress(0x17C00000, 0x100);
if (pBuf2 == NULL) return (FALSE);
RETAILMSG(1, (TEXT("CPLDS VIRTUAL ADDRESS -> 0x%08X\r\n"), pBuf2));
RETAILMSG(1,(TEXT("CPLDS Value -> 0x%08X\r\n"),(*(volatile PULONG)(pBuf2+0x38))));
*(volatile PULONG) (pBuf2+0x38) = (*(volatile PULONG)(pBuf2+0x38)) & ~0x10;
RETAILMSG(1,(TEXT("CPLDS Value -> 0x%08X\r\n"),(*(volatile PULONG)(pBuf2+0x38))));
UnMapMemory(pBuf2, 0x100);
#endif // ACCELENT
}
#endif // XSCALE
// PHYSICAL_ADDRESS ioPhysicalBase;
RETAILMSG(1, (TEXT("Detect Card\r\n")));
pss->m_nChipID = CHIPID_SM501;
#ifndef UMA
pss->m_pLAW = (unsigned char *)VirtualAddress(pss->m_nLAWPhysical, pss->MaxVideoMemorySize());
#else
PUCHAR pAddr = (PUCHAR)VirtualAlloc(0, pss->MaxVideoMemorySize(), MEM_RESERVE, PAGE_NOACCESS);
VirtualCopy((void *)pAddr, (void *)pss->m_nLAWPhysical, pss->MaxVideoMemorySize(), PAGE_READWRITE | PAGE_NOCACHE);
pss->m_pLAW = (PUCHAR)pAddr;
#endif
if (pss->m_pLAW == NULL)
return (FALSE);
RETAILMSG(1, (TEXT("m_pLAW = 0x%08X\r\n"), pss->m_pLAW));
pss->m_pREG = (unsigned char *)VirtualAddress(pss->m_nREGPhysical, pss->RegMemorySize());
RETAILMSG(1, (TEXT("m_pREG = 0x%08X\r\n"), pss->m_pREG));
return (TRUE);
// ****************************************************************
#else // For Regular CEPC detection
PCI_SLOT_NUMBER slotNumber;
ULONG bus, device, function;
ULONG length;
PCI_COMMON_CONFIG pciConfig;
int nMonNo = nMonitorNo;
for (bus = 0; bus < PCI_MAX_BUS; bus++)
{
for (device = 0; device < PCI_MAX_DEVICES; device++)
{
slotNumber.u.bits.DeviceNumber = device;
for (function = 0; function < PCI_MAX_FUNCTION; function++)
{
slotNumber.u.bits.FunctionNumber = function;
length = HalGetBusDataByOffset(PCIConfiguration, bus,
slotNumber.u.AsULONG, &pciConfig,
0, sizeof(pciConfig));
if (length == 0 || pciConfig.VendorID == 0xFFFF)
break;
else
{
if ((pciConfig.VendorID == PCI_VENDOR_SMI) &&
(pciConfig.BaseClass == PCI_CLASS_DISPLAY) &&
((pciConfig.SubClass == PCI_SUBCLASS_DISPLAY) || (pciConfig.SubClass == 0x80))
)
{
if (pss->isSupportedChipID(pciConfig.DeviceID))
{
// Check counter to make sure that we find the
// correct card instance
if (nMonNo-- != 0)
break;
length = HalGetBusDataByOffset(PCIConfiguration, bus,
slotNumber.u.AsULONG, &pciConfig,
0, sizeof(pciConfig));
// Patch Alpha chip and its ID
if ((pciConfig.RevisionID == 0xA0) &&
(pciConfig.DeviceID == CHIPID_SM501ALPHA)) // RevA Patch
{
DWORD dwBaseAdd = 0x80000000; //pciConfig.Command | 0x07;
HalSetBusDataByOffset (PCIConfiguration, bus,
slotNumber.u.AsULONG, &dwBaseAdd, 0x10, 0x04);
length = HalGetBusDataByOffset(PCIConfiguration, bus,
slotNumber.u.AsULONG, &pciConfig,
0, sizeof(pciConfig));
}
if (pciConfig.DeviceID == CHIPID_SM501ALPHA)
pciConfig.DeviceID = CHIPID_SM501;
pss->m_nChipID = pciConfig.DeviceID;
pss->m_IRQ = pciConfig.u.type0.InterruptLine;
pss->m_nLAWPhysical = pciConfig.u.type0.BaseAddresses[0];
pss->m_nREGPhysical = pciConfig.u.type0.BaseAddresses[1];
pss->m_nBusNo = bus;
pss->m_nSlotNo = slotNumber.u.AsULONG;
pss->m_pLAW = VirtualAddress(pss->m_nLAWPhysical,
pss->MaxVideoMemorySize());
if (pss->m_pLAW == NULL)
return (FALSE);
pss->m_pREG = VirtualAddress(pss->m_nREGPhysical,
pss->RegMemorySize());
if (pss->m_pREG == NULL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -