📄 pcibus.c
字号:
// 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 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->DllName, 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
)
{
PCI_SLOT_NUMBER slotNumber;
PCI_COMMON_CONFIG pciConfig;
PCI_DEV_INFO Info;
int bus, 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 = 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;
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)
PCIInitDevice(&Info);
// Request I/O and IRQ resources for device (phase 1 only)
if (Phase1 && !PCIRequestResources(&Info)) {
RETAILMSG(1, (L"PCIbus!PCIEnum: WARNING: Resource request for device %d:%d:%d failed\r\n", bus, device, function));
}
// Search for match in registry and configure
PCIReg(&Info);
// Dump PCI configuration register to debug out (DEBUG only)
DUMPPCICFG(&Info);
if (function == 0 && !(pciConfig.HeaderType & PCI_MULTIFUNCTION)) {
// Not a multi-function device, continue on to next device
break;
}
}
// Error on HalGetBusData, move on to next bus
if (length == 0) {
break;
}
}
if (length == 0 && device == 0) {
// Bus doesn't exist, exit
break;
}
}
return TRUE;
}
//
// Find a match for a device in the registry.
//
static BOOL
PCIReg(
PPCI_DEV_INFO pInfo
)
{
WCHAR SavePath[DEVKEY_LEN];
DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIReg+(%s, %d, %d, %d)\r\n", pInfo->RegPath, pInfo->Bus, pInfo->Device, pInfo->Function));
wcsncpy(SavePath, pInfo->RegPath, DEVKEY_LEN - 1);
SavePath[DEVKEY_LEN - 1] = L'\0'; // make sure longest string is terminated
// Fail if key name too long
if (wcslen(SavePath) + wcslen(L"\\") + wcslen(PCIBUS_INSTANCE_KEYNAME) >= DEVKEY_LEN) {
wcscpy(pInfo->RegPath, SavePath);
return FALSE;
}
// Check for exact match under Instance sub-key
wcscat(pInfo->RegPath, L"\\");
wcscat(pInfo->RegPath, PCIBUS_INSTANCE_KEYNAME);
if (RegMatch(pInfo) == PCIBUS_MATCH_ALL) {
// Get registry flags
RegGetFlags(pInfo);
// There is an exact instance match already, so don't do anything except re-request SYSINTR
return RegSetConfig(pInfo);
}
// Fail if key name too long
if (wcslen(SavePath) + wcslen(L"\\") + wcslen(PCIBUS_TEMPLATE_KEYNAME) >= DEVKEY_LEN) {
wcscpy(pInfo->RegPath, SavePath);
return FALSE;
}
// No instance exists, so check for potential match under Template key
wcscpy(pInfo->RegPath, SavePath);
wcscat(pInfo->RegPath, L"\\");
wcscat(pInfo->RegPath, PCIBUS_TEMPLATE_KEYNAME);
if (RegMatch(pInfo) == PCIBUS_MATCH_NONE) {
// There is nothing that matches the device in the registry, return with error
wcscpy(pInfo->RegPath, SavePath);
return FALSE;
}
// Get registry flags
RegGetFlags(pInfo);
// A match in the registry exists, copy Template to Instance and generate device location info
return RegCopy(pInfo);
}
//
// Function to clean stale registry entries
//
static BOOL
PCIRegClean(LPCWSTR EnumKey)
{
HKEY Key;
DWORD NumDevKeys;
DWORD LongSubKey;
DWORD status;
DWORD ValLen;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -