📄 pcienum.cpp
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
// Routines to Bus Support the PCIbus
//
#include <windows.h>
#include <types.h>
#include <pcienum.h>
#include <pcidbg.h>
#include <pcibus.h>
#include <CeBusCfg.h>
PciDeviceFolder::PciDeviceFolder(LPCTSTR lpBusName,LPCTSTR lpTemplateRegPath,DWORD dwBusType, DWORD BusNumber,PCI_SLOT_NUMBER SlotNumber,HANDLE hParent)
: DeviceFolder(lpBusName,lpTemplateRegPath,dwBusType,BusNumber,SlotNumber.u.bits.DeviceNumber,SlotNumber.u.bits.FunctionNumber, hParent)
{
m_CurPowerState=D0;
m_CurSleepPowerState = D4;
m_ConfigureIsBackuped = FALSE;;
m_pCfg= new PCI_COMMON_CONFIG;
m_fAlwaysBackup = FALSE;
m_dwPowerMgrOffset = 0;
FindPCIPowerMgrInterface();
}
PciDeviceFolder::~PciDeviceFolder()
{
if (m_pCfg)
delete m_pCfg;
}
// PCI Power Handling;
BOOL PciDeviceFolder::SetPowerState(CEDEVICE_POWER_STATE newPowerState)
{
Lock();
if (m_pCfg) {
if (newPowerState==D4 && m_CurPowerState!=D4) { // Change from DX to D4. backup the configuration.
m_ConfigureIsBackuped= BackupConfiguration();
};
if (newPowerState!=D4 && m_CurPowerState == D4) { // Out or D4, restore the configurate
if (m_ConfigureIsBackuped) {
RestoreConfiguration();
m_ConfigureIsBackuped = FALSE;
}
}
}
if (newPowerState!=m_CurPowerState) {
SetPciPowerState(newPowerState);
m_CurPowerState=newPowerState;
};
// When SetPowerState is called. It means this driver is under Power Managment Control.
// Sleep Power State is no longer D4. It is always sync with Currrent Power State.
m_CurSleepPowerState = newPowerState;
Unlock();
return TRUE;
}
BOOL PciDeviceFolder::PowerUp()
{
if (GetDeviceHandle()!=NULL && m_CurPowerState != m_CurSleepPowerState&& m_pCfg && m_ConfigureIsBackuped ) {
SetPciPowerState(m_CurPowerState);
if (m_CurSleepPowerState == D4 || m_fAlwaysBackup ) {
RestoreConfiguration();
m_ConfigureIsBackuped = FALSE;
}
SetPciPowerState(m_CurPowerState);
}
return TRUE;
}
BOOL PciDeviceFolder::PowerDown()
{
if (GetDeviceHandle()!=NULL && m_CurPowerState != m_CurSleepPowerState && m_pCfg ) {
if (m_CurSleepPowerState == D4 || m_fAlwaysBackup )
m_ConfigureIsBackuped= BackupConfiguration();
SetPciPowerState(m_CurSleepPowerState);
}
return TRUE;
}
BOOL PciDeviceFolder::RestoreConfiguration()
{
if (m_pCfg) {
CE_BUS_DEVICE_CONFIGURATION_DATA deviceConfigData;
deviceConfigData.lpDeviceBusName=NULL;
deviceConfigData.dwSpace=PCI_WHICHSPACE_CONFIG;
deviceConfigData.dwOffset=0;
deviceConfigData.dwLength = sizeof(PCI_COMMON_CONFIG);
deviceConfigData.pBuffer = m_pCfg;
return SetConfigurationData(&deviceConfigData);
}
else
return FALSE;
}
BOOL PciDeviceFolder::BackupConfiguration()
{
if (m_pCfg) {
CE_BUS_DEVICE_CONFIGURATION_DATA deviceConfigData;
deviceConfigData.lpDeviceBusName=NULL;
deviceConfigData.dwSpace=PCI_WHICHSPACE_CONFIG;
deviceConfigData.dwOffset=0;
deviceConfigData.dwLength = sizeof(PCI_COMMON_CONFIG);
deviceConfigData.pBuffer = m_pCfg;
m_ConfigureIsBackuped = GetConfigurationData(&deviceConfigData);
return (m_ConfigureIsBackuped);
}
else
return FALSE;
}
BOOL PciDeviceFolder::FindPCIPowerMgrInterface()
{
PCI_COMMON_CONFIG pciCmnCfg;
CE_BUS_DEVICE_CONFIGURATION_DATA deviceConfigData;
deviceConfigData.lpDeviceBusName=NULL;
deviceConfigData.dwSpace=PCI_WHICHSPACE_CONFIG;
deviceConfigData.dwOffset=0;
deviceConfigData.dwLength = sizeof(PCI_COMMON_CONFIG);
deviceConfigData.pBuffer = &pciCmnCfg;
if (GetConfigurationData(&deviceConfigData)) {
if (pciCmnCfg.Status & 0x10) { // This one support Power Mgr.
DWORD dwCapPtr = 0;
// Search to find Power Mgr Register.
switch (pciCmnCfg.HeaderType & 0x7f) {
case PCI_DEVICE_TYPE: // PCI Bus Power Mgr Specification 3.1.1
dwCapPtr = *(((PBYTE)&pciCmnCfg)+ 0x34);
break;
case PCI_BRIDGE_TYPE:
dwCapPtr = *(((PBYTE)&pciCmnCfg)+ 0x34);
break;
case PCI_CARDBUS_TYPE:
dwCapPtr = *(((PBYTE)&pciCmnCfg)+ 0x14);
break;
default:
break;
}
if (dwCapPtr!=0 && dwCapPtr <= sizeof(pciCmnCfg) - sizeof(PCI_POWER_MANAGEMENT_BLOCK) ) {
PPCI_POWER_MANAGEMENT_BLOCK pPmcBlock =(PPCI_POWER_MANAGEMENT_BLOCK)(((PBYTE)&pciCmnCfg) + dwCapPtr);
// Search for PM Regs.
while (pPmcBlock->CapabilityID!=0x1 && pPmcBlock->NextItemPtr != NULL
&& pPmcBlock->NextItemPtr <= sizeof(pciCmnCfg) - sizeof(PCI_POWER_MANAGEMENT_BLOCK)) {
pPmcBlock = (PPCI_POWER_MANAGEMENT_BLOCK)(((PBYTE)&pciCmnCfg) + pPmcBlock->NextItemPtr);
}
if (pPmcBlock->CapabilityID==0x1
&& pPmcBlock->NextItemPtr <= sizeof(pciCmnCfg) - sizeof(PCI_POWER_MANAGEMENT_BLOCK)) {
// We found it.
m_dwPowerMgrOffset = (DWORD)((PBYTE)pPmcBlock - (PBYTE)&pciCmnCfg);
ASSERT( m_dwPowerMgrOffset < sizeof(pciCmnCfg) - sizeof(PCI_POWER_MANAGEMENT_BLOCK));
CE_BUS_DEVICE_CONFIGURATION_DATA deviceConfigData1;
deviceConfigData1.lpDeviceBusName=NULL;
deviceConfigData1.dwSpace=PCI_WHICHSPACE_CONFIG;
deviceConfigData1.dwOffset= m_dwPowerMgrOffset ;
deviceConfigData1.dwLength = sizeof(m_PowerMgrBlock);
deviceConfigData1.pBuffer = &m_PowerMgrBlock;
if (!GetConfigurationData(&deviceConfigData1)) { // If this fails. Make it un-spported.
m_dwPowerMgrOffset=0;
}
}
}
}
}
return (m_dwPowerMgrOffset!=0);
}
BOOL PciDeviceFolder::SetPciPowerState(CEDEVICE_POWER_STATE curPowerState)
{
BOOL bReturn = FALSE;
if (m_dwPowerMgrOffset!=0) {
CE_BUS_DEVICE_CONFIGURATION_DATA deviceConfigData;
deviceConfigData.lpDeviceBusName=NULL;
deviceConfigData.dwSpace=PCI_WHICHSPACE_CONFIG;
deviceConfigData.dwOffset=0;
deviceConfigData.dwLength = sizeof(m_PowerMgrBlock);
deviceConfigData.pBuffer = &m_PowerMgrBlock;
if (!GetConfigurationData(&deviceConfigData)) { // If this fails. Make it un-spported.
// PCI Power Mgr Spec 3.2.4
DWORD dwPciState = 0;
switch ( curPowerState) {
case D0:
default:
dwPciState = 0;
break;
case D1:
dwPciState = 1;
break;
case D2:
dwPciState = 2;
break;
case D3: { // We only consern about wakeup source.
// find next Higher state that can support wakeup source.
DWORD dwBit = 0x4000; // Bit 14(D3) for D3 hot
for (dwPciState = 3 ; dwPciState!=0; dwPciState -- ) {
if ((m_PowerMgrBlock.PMC & dwBit)!=0)
break;
dwBit >>=1;
}
break;
}
case D4:
dwPciState = 3;
break;
}
m_PowerMgrBlock.PMCSR = ((m_PowerMgrBlock.PMCSR) & (~0x3)) + (UINT16)(dwPciState & 0x3);
deviceConfigData.lpDeviceBusName=NULL;
deviceConfigData.dwSpace=PCI_WHICHSPACE_CONFIG;
deviceConfigData.dwOffset=0;
deviceConfigData.dwLength = sizeof(m_PowerMgrBlock);
deviceConfigData.pBuffer = &m_PowerMgrBlock;
bReturn = SetConfigurationData(&deviceConfigData);
}
}
return bReturn;
}
//-------------------------------------PCI Bus Driver -------------------------------------------------------
PciBusEnum::PciBusEnum(LPCTSTR lpActiveRegPath,LPCTSTR lpInstanceRegPath)
: DefaultBusDriver(lpActiveRegPath)
, m_ActiveKey(HKEY_LOCAL_MACHINE, lpActiveRegPath)
, m_DeviceKey(HKEY_LOCAL_MACHINE,lpInstanceRegPath)
{
DEBUGMSG(ZONE_ENUM| ZONE_INIT,(TEXT("BusEnum::BusEnum (ActivateRegPath=%s)\r\n"),lpActiveRegPath));
// Get DEVLOAD_DEVKEY_VALNAME name
m_lpActiveRegPath = NULL;
DWORD dwKeyLen=0;
if (lpInstanceRegPath!=NULL) {
dwKeyLen = _tcslen(lpInstanceRegPath) + 1;
m_lpActiveRegPath = new TCHAR [dwKeyLen];
if ( m_lpActiveRegPath) {
_tcscpy(m_lpActiveRegPath,lpInstanceRegPath);
m_lpActiveRegPath [dwKeyLen-1]= 0;
}
}
m_lpStrInitParam = NULL;
m_dwNumOfInitParam =0 ;
m_lpBusName = NULL;
m_dwBusNumber = 0;
m_dwDeviceIndex = 0;
m_dwCfgAlwaysBackup = 0;
}
PciBusEnum::~PciBusEnum()
{
if (m_lpStrInitParam )
delete m_lpStrInitParam ;
if ( m_lpBusName)
delete m_lpBusName;
if (m_lpActiveRegPath)
delete m_lpActiveRegPath;
}
#define BUSNAMEUNKNOWN TEXT("UnknownBus")
BOOL PciBusEnum::Init()
{
BOOL bReturn = FALSE;
// Initialize InitParam
if ( m_lpActiveRegPath==NULL || !m_ActiveKey.IsKeyOpened()) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,(TEXT("PciBusEnum!Init RegOpenKeyEx() return FALSE!!!\r\n")));
return FALSE;
}
if (m_lpStrInitParam == NULL ) {
DWORD dwKeyLen=0;
DWORD dwType;
// BC. It is BC with RegEnum We may want remove this later
// What this key contain multi-string that indicate the reigstry has such name will copy into active registry
if (m_ActiveKey.RegQueryValueEx(DEVLOAD_REPARMS_VALNAME, &dwType,NULL,&dwKeyLen) && dwType== REG_MULTI_SZ && dwKeyLen!=0 ) {
dwKeyLen = (dwKeyLen + sizeof(TCHAR) -1 ) / sizeof(TCHAR);
m_lpStrInitParam = new TCHAR [ dwKeyLen ];
if (m_lpStrInitParam) {
if (m_ActiveKey.GetRegValue(DEVLOAD_REPARMS_VALNAME,(LPBYTE)m_lpStrInitParam,dwKeyLen * sizeof(TCHAR))) {
DWORD dwUnitCount= dwKeyLen;
for (LPTSTR lpCurPos = m_lpStrInitParam;
m_dwNumOfInitParam< MAX_INITPARAM && dwUnitCount!=0 && *lpCurPos!=0 ;
m_dwNumOfInitParam++) {
m_lpInitParamArray[m_dwNumOfInitParam] = lpCurPos;
while (*lpCurPos!=0 && dwUnitCount!=0 ) {
lpCurPos++;
dwUnitCount --;
}
if (dwUnitCount) {
lpCurPos ++;
dwUnitCount --;
}
else
break;
}
}
}
}
}
if (!m_ActiveKey.IsKeyOpened() || !m_ActiveKey.GetRegValue(PCI_ALWAYSBACKUP,(LPBYTE)m_dwCfgAlwaysBackup,sizeof(m_dwCfgAlwaysBackup))) {
m_dwCfgAlwaysBackup = 0;
}
// Scan And Enum All the driver in registry.
if ( GetDeviceHandle()!=NULL && m_DeviceKey.IsKeyOpened()) {
DWORD dwKeyLen=0;
DWORD dwType;
if (!m_DeviceKey.GetRegValue(DEVLOAD_INTERFACETYPE_VALNAME,(PUCHAR) &m_dwBusType,sizeof(m_dwBusType))) {
// No interface type defined
m_dwBusType=InterfaceTypeUndefined;
};
dwKeyLen=0;
if (m_lpBusName == NULL && m_DeviceKey.RegQueryValueEx(DEVLOAD_BUSNAME_VALNAME, &dwType,NULL,&dwKeyLen) && dwType== DEVLOAD_BUSNAME_VALTYPE && dwKeyLen!=0 ) {
dwKeyLen = (dwKeyLen + sizeof(TCHAR) -1) / sizeof(TCHAR);
m_lpBusName = new TCHAR[dwKeyLen];
if (m_lpBusName ) {
m_DeviceKey.GetRegValue(DEVLOAD_BUSNAME_VALNAME, (LPBYTE )m_lpBusName, dwKeyLen*sizeof(TCHAR) );
m_lpBusName [dwKeyLen-1]=0;
}
}
if (!m_DeviceKey.GetRegValue(DEVLOAD_BUSNUMBER_VALNAME , (LPBYTE)m_dwBusNumber,sizeof(m_dwBusNumber)))
m_dwBusNumber=0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -