📄 pcibus.c
字号:
// ConfigDllName value doesn't exist
wcscpy(pInfo->ConfigDllName, L"");
ConfigDllExists = FALSE;
}
}
//
// Read Dll value (if it exists)
//
ValLen = sizeof(pInfo->DllName);
Status = RegQueryValueEx(Key, DEVLOAD_DLLNAME_VALNAME, NULL, &ValType, (PUCHAR)pInfo->DllName, &ValLen);
if ((Status != ERROR_SUCCESS) || (ValType != DEVLOAD_DLLNAME_VALTYPE)) {
// Dll value doesn't exist
wcscpy(pInfo->DllName, L"");
DllExists = FALSE;
}
// Make sure there is a DLL to load with the ConfigEntry
if (pInfo->ConfigEntry) {
if (!ConfigDllExists && !DllExists) {
// Neither ConfigDll or Dll names exist, so invalidate ConfigEntry
DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetInfo: Registry value '%s\\%s' exists but no '%s' or '%s' values are specified. Ignoring '%s' value.\r\n",
pInfo->RegPath, PCIBUS_CONFIGENTRY_VALNAME, PCIBUS_CONFIGDLL_VALNAME, DEVLOAD_DLLNAME_VALNAME, PCIBUS_CONFIGENTRY_VALNAME));
pInfo->ConfigEntry = FALSE;
wcscpy(pInfo->ConfigEntryName, L"");
} else if (!ConfigDllExists && DllExists) {
// No ConfigDll value, so use Dll value for ConfigEntry
wcscpy(pInfo->ConfigDllName, pInfo->DllName);
}
}
//
// Read Flags value (if it exists)
//
ValLen = sizeof(pInfo->DevFlags);
Status = RegQueryValueEx(Key, DEVLOAD_FLAGS_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);
if ((Status == ERROR_SUCCESS) && (ValType == DEVLOAD_FLAGS_VALTYPE)) {
// Flags value exists
pInfo->DevFlags = Val;
}
//
// Read Command value (if it exists)
//
ValLen = sizeof(Val);
Status = RegQueryValueEx(Key, PCIBUS_COMMAND_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);
if ((Status == ERROR_SUCCESS) && (ValType == PCIBUS_COMMAND_VALTYPE)) {
// Command value exists
pInfo->Command = Val;
}
//
// Read BridgeCommand value (if it exists)
//
ValLen = sizeof(Val);
Status = RegQueryValueEx(Key, PCIBUS_BRIDGECONTROL_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);
if ((Status == ERROR_SUCCESS) && (ValType == PCIBUS_BRIDGECONTROL_VALTYPE)) {
// BridgeControl value exists
pInfo->BridgeControl = Val;
}
//
// Read Latency value (if it exists)
//
ValLen = sizeof(Val);
Status = RegQueryValueEx(Key, PCIBUS_LATENCY_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);
if ((Status == ERROR_SUCCESS) && (ValType == PCIBUS_LATENCY_VALTYPE)) {
// Latency value exists
pInfo->Latency = Val;
}
//
// Read Latency value (if it exists)
//
ValLen = sizeof(Val);
Status = RegQueryValueEx(Key, PCIBUS_SECONDARYLATENCY_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);
if ((Status == ERROR_SUCCESS) && (ValType == PCIBUS_SECONDARYLATENCY_VALTYPE)) {
// Latency value exists
pInfo->SecondaryLatency = Val;
}
RegCloseKey(Key);
return TRUE;
}
//
// Get Prefetch Memory Window from registry.
//
BOOL
RegGetExtraDeviceInfo(
PPCI_DEV_INFO_EX pInfo
)
{
HKEY Key;
DWORD Status;
BOOL ConfigDllExists = TRUE;
BOOL DllExists = TRUE;
DWORD dwValType, ValLen;
//
// Open key to be enumerated
//
Status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pInfo->pciDevice.RegPath,
0,
0,
&Key);
if (Status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
(TEXT("PCIBUS!RegGetExtraDeviceInfo RegOpenKeyEx(%s) returned %d.\r\n"),
pInfo->pciDevice.RegPath, Status));
return FALSE;
}
//
// Read BusNumber Base and Length.
//
ValLen = sizeof(pInfo->dwBusNumberBase);
if (RegQueryValueEx(Key, PCIBUS_BUSNUMBERBASE_VALNAME, NULL, &dwValType, (PBYTE)&(pInfo->dwBusNumberBase), &ValLen) == ERROR_SUCCESS &&
dwValType == PCIBUS_BUSNUMBERBASE_VALTYPE ) {
if (RegQueryValueEx(Key, PCIBUS_BUSNUMBERLENGTH_VALNAME, NULL, &dwValType, (PBYTE)&(pInfo->dwBusNumberLength), &ValLen) == ERROR_SUCCESS &&
dwValType == PCIBUS_BUSNUMBERLENGTH_VALTYPE ) {
}
else {
pInfo->dwBusNumberLength = PCI_MAX_BUS ;
}
}
else {
pInfo->dwBusNumberBase = 0;
pInfo->dwBusNumberLength = PCI_MAX_BUS;
}
pInfo->dwBusNumberLength = min (pInfo->dwBusNumberLength, PCI_MAX_BUS);
//
// Read MemBase and MemLen values.
//
pInfo->PrefetchMemBase.Num = PCI_TYPE0_ADDRESSES;
if (!RegGetList(Key, PCIBUS_PREFETCH_MEMBASE_VALNAME, &pInfo->PrefetchMemBase.Num, pInfo->PrefetchMemBase.Reg) && (pInfo->PrefetchMemBase.Num == PCI_TYPE0_ADDRESSES)) {
DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetExtraDeviceInfo: Registry value '%s\\%s' has more than %d items in multi_sz list. Ignoring the additional items.\r\n",
pInfo->pciDevice.RegPath, PCIBUS_PREFETCH_MEMBASE_VALNAME, PCI_TYPE0_ADDRESSES));
}
pInfo->PrefetchMemLen.Num = PCI_TYPE0_ADDRESSES;
if (!RegGetList(Key, PCIBUS_PREFETCH_MEMLEN_VALNAME, &pInfo->PrefetchMemLen.Num, pInfo->PrefetchMemLen.Reg) && (pInfo->PrefetchMemLen.Num == PCI_TYPE0_ADDRESSES)) {
DEBUGMSG(ZONE_WARNING, (L"PCIBUS!RegGetExtraDeviceInfo: Registry value '%s\\%s' has more than %d items in multi_sz list. Ignoring the additional items.\r\n",
pInfo->pciDevice.RegPath, PCIBUS_PREFETCH_MEMLEN_VALNAME, PCI_TYPE0_ADDRESSES));
}
RegCloseKey(Key);
return TRUE;
}
//
// Get Flags value from registry.
//
static BOOL
RegGetFlags(
PPCI_DEV_INFO pInfo
)
{
HKEY Key;
DWORD Status;
DWORD ValLen, ValType, Val;
//
// Open key to be enumerated
//
Status = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pInfo->RegPath,
0,
0,
&Key);
if (Status != ERROR_SUCCESS) {
DEBUGMSG(ZONE_ENUM|ZONE_ERROR,
(TEXT("PCIBUS!RegGetFlags RegOpenKeyEx(%s) returned %d.\r\n"),
pInfo->RegPath, Status));
return FALSE;
}
//
// Read Flags value (if it exists)
//
ValLen = sizeof(pInfo->DevFlags);
Status = RegQueryValueEx(Key, DEVLOAD_FLAGS_VALNAME, NULL, &ValType, (PUCHAR)&Val, &ValLen);
if ((Status == ERROR_SUCCESS) && (ValType == DEVLOAD_FLAGS_VALTYPE)) {
// Flags value exists
pInfo->DevFlags = Val;
} else {
pInfo->DevFlags = DEVFLAGS_NONE;
}
RegCloseKey(Key);
return TRUE;
}
//
// Load configuration routine DLL and map entry point.
//
BOOL
LoadConfigEntry(
PPCI_DEV_INFO pInfo
)
{
PFN_CONFIGENTRY ConfigEntryFn;
HMODULE hDll;
// If ConfigEntry, load config DLL and get ConfigEntry address
if (pInfo->ConfigEntry) {
if (pInfo->DevFlags & DEVFLAGS_LOADLIBRARY) {
hDll = LoadLibrary(pInfo->ConfigDllName);
} else {
hDll = LoadDriver(pInfo->ConfigDllName);
}
if (hDll != NULL) {
// Driver/library load successful, get ConfigEntry address
ConfigEntryFn = (PFN_CONFIGENTRY)GetProcAddress(hDll, pInfo->ConfigEntryName);
if (ConfigEntryFn == NULL) {
DEBUGMSG(ZONE_ERROR, (L"PCIBUS!GetConfigEntry: GetProcAddr(%s, %s) failed with error %d.\r\n",
pInfo->DllName, pInfo->ConfigEntryName, GetLastError()));
FreeLibrary(hDll);
goto GetConfigEntry_EXIT;
}
// Create ConfigInfo node and place into list
pInfo->ConfigInfo = AddConfigInfo(hDll, ConfigEntryFn);
if (pInfo->ConfigInfo == NULL) {
DEBUGMSG(ZONE_ERROR, (L"PCIBUS!GetConfigEntry: AddConfigInfo( ) failed, out of memory.\r\n"));
FreeLibrary(hDll);
goto GetConfigEntry_EXIT;
}
return TRUE;
} else {
// Driver/library load not successful, ConfigEntry becomes false
DEBUGMSG(ZONE_ERROR, (L"PCIBUS!GetConfigEntry: LoadDriver/Library(%s) failed with error %d.\r\n", pInfo->ConfigDllName, GetLastError()));
goto GetConfigEntry_EXIT;
}
}
GetConfigEntry_EXIT:
pInfo->ConfigEntry = FALSE;
wcscpy(pInfo->ConfigEntryName, L"");
wcscpy(pInfo->DllName, L"");
pInfo->ConfigInfo = NULL;
return FALSE;
}
//
// Unload configuration routine DLLs.
//
void
UnloadConfigEntrys(
void
)
{
DelConfigInfoList( );
}
//
// Add configuration DLL handles to tracking list.
//
static PPCI_CFG_INFO
AddConfigInfo(
HMODULE hDll,
PFN_CONFIGENTRY ConfigEntryFn
)
{
PPCI_CFG_INFO ci = (PPCI_CFG_INFO)LocalAlloc(0, sizeof(PCI_CFG_INFO));
if (!ci) return NULL;
ci->hDll = hDll;
ci->ConfigEntryFn = ConfigEntryFn;
ci->Next = g_ConfigInfoList;
g_ConfigInfoList = ci;
return ci;
}
//
// Delete configuration DLL handles from tracking list and unload them.
//
static void
DelConfigInfoList(
void
)
{
PPCI_CFG_INFO ni;
PPCI_CFG_INFO ci = g_ConfigInfoList;
while (ci) {
ni = ci->Next;
FreeLibrary(ci->hDll);
LocalFree(ci);
ci = ni;
}
g_ConfigInfoList = NULL;
}
#ifdef DEBUG
#define DUMPPCICFG(X) { \
if (ZONE_INIT) DumpPciConfig(X); \
}
#else
#define DUMPPCICFG(X) ((void)0)
#endif
BOOL IsSystemPhase1()
{
HANDLE hEvent;
static BOOL Phase1 = TRUE;
// Find out whether or not we're in boot phase 1 or 2
if ( Phase1 && (hEvent = OpenEvent(EVENT_ALL_ACCESS, FALSE, TEXT("SYSTEM/BootPhase2")))!=NULL) {
if (WaitForSingleObject(hEvent, 0) == WAIT_OBJECT_0) {
// We're in boot phase 2
Phase1 = FALSE;
}
CloseHandle(hEvent);
}
return Phase1;
}
//
// Enumerate PCIbus.
//
static BOOL
PCIEnum(
LPCWSTR EnumKey, DWORD dwBusNumberBase, DWORD dwBusNameLength
)
{
PCI_SLOT_NUMBER slotNumber;
PCI_COMMON_CONFIG pciConfig;
PCI_DEV_INFO Info;
DWORD bus;
int device, function;
int length;
BOOL Phase1 = IsSystemPhase1();
DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIEnum(%s), Boot phase %d\r\n", EnumKey, (Phase1) ? 1 : 2));
slotNumber.u.AsULONG = 0;
// Scan bus
for (bus = dwBusNumberBase; bus < dwBusNumberBase + dwBusNameLength; 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;
pciConfig.VendorID = 0xFFFF;
pciConfig.HeaderType = 0;
length = HalGetBusData(
PCIConfiguration,
bus,
slotNumber.u.AsULONG,
&pciConfig,
sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific)
);
if (length != (sizeof(pciConfig) - sizeof(pciConfig.DeviceSpecific)) ||
(pciConfig.DeviceID == PCI_INVALID_DEVICEID) || (pciConfig.VendorID == PCI_INVALID_VENDORID) || (pciConfig.VendorID == 0)) {
// No function found
if (function != 0) {
// If a multi-function device, continue to next function
continue;
} else {
// If not a multi-function device, continue to next device
break;
}
}
// Initialize out device info
PCIInitInfo(EnumKey, bus, device, function, &pciConfig, &Info);
// Get BAR length information, either from registry or from h/w
PCIGetBARs(&Info);
// Complete device's final initialization step (if it has one)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -