⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcibus.c

📁 PCI总线的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
            // 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 + -