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

📄 pcibus.c

📁 PCI总线的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
        ValLen = sizeof(Val32);
        status = RegQueryValueEx(DevKey, PCIBUS_DEVICENUMBER_VALNAME, NULL, &ValType, (PUCHAR)&Val32, &ValLen);
                    
        if (status != ERROR_SUCCESS) {
            // No DeviceNumber value found
            goto RegMatchOne_Exit;
        }

        if (Val32 != pInfo->Device) {
            // Device number doesn't match
            Match = 0;
            goto RegMatchOne_Exit;
        } else {
            DEBUGMSG(ZONE_ENUM, (TEXT("PCIBUS!RegMatchOne Match for DeviceNumber (0x%X) found.\r\n"), Val32));
            
            Match++;
        }

        //
        // Examine FunctionNumber value, check against device's function number
        //
        ValLen = sizeof(Val32);
        status = RegQueryValueEx(DevKey, PCIBUS_FUNCTIONNUMBER_VALNAME, NULL, &ValType, (PUCHAR)&Val32, &ValLen);
                    
        if (status != ERROR_SUCCESS) {
            // No FunctionNumber value found
            goto RegMatchOne_Exit;
        }

        if (Val32 != pInfo->Function) {
            // Function number doesn't match
            Match = 0;
            goto RegMatchOne_Exit;
        } else {
            DEBUGMSG(ZONE_ENUM, (TEXT("PCIBUS!RegMatchOne Match for FunctionNumber (0x%X) found.\r\n"), Val32));
            
            Match++;
        }
 
RegMatchOne_Exit:
    RegCloseKey(DevKey);
        
    return Match;
}


//
// Search registry for best device/registry match.
//
DWORD
RegMatch(
    PPCI_DEV_INFO pInfo
    )
{
    HKEY Key;
    DWORD DevLoadOrder;
    DWORD LoadOrder;
    DWORD NumDevKeys;
    DWORD RegEnum;
    DWORD status;
    DWORD ValType;
    DWORD ValLen;
    DWORD Match = 0;
    DWORD BestMatch = 0;
    WCHAR DevName[DEVNAME_LEN];
    WCHAR RegPath[DEVKEY_LEN]; 

    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!RegMatch+(%s, %d, %d, %d)\r\n", pInfo->RegPath, pInfo->Bus, pInfo->Device, pInfo->Function));

    //
    // 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!RegMatch RegOpenKeyEx(%s) returned %d.\r\n"), pInfo->RegPath, status));
        return 0;
    }

    //
    // Find out how many sub-keys there are
    //
    status = RegQueryInfoKey(
                    Key,
                    NULL,         // class name buffer (lpszClass)
                    NULL,       // ptr to length of class name buffer (lpcchClass)
                    NULL,           // reserved
                    &NumDevKeys,    // ptr to number of subkeys (lpcSubKeys)
                    &ValType,       // ptr to longest subkey name length (lpcchMaxSubKeyLen)
                    &ValLen,        // ptr to longest class string length (lpcchMaxClassLen)
                    &LoadOrder,     // ptr to number of value entries (lpcValues)
                    &DevLoadOrder,  // ptr to longest value name length (lpcchMaxValueNameLen)
                    &ValLen,        // ptr to longest value data length (lpcbMaxValueData)
                    NULL,           // ptr to security descriptor length
                    NULL);          // ptr to last write time
                    
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (TEXT("PCIBUS!RegMatch RegQueryInfoKey(Class) returned %d.\r\n"), status));
        RegCloseKey(Key);
        return 0;
    }
    
    DEBUGMSG(ZONE_ENUM,
        (TEXT("PCIBUS!RegMatch %d devices to search\r\n"), NumDevKeys));

    //
    // Base registry key
    //
    wcsncpy(RegPath, pInfo->RegPath, DEVKEY_LEN);

    //
    // Search for closest match
    //
    RegEnum = 0; 
    
    for (RegEnum = 0; RegEnum < NumDevKeys; RegEnum++) {
        DEBUGMSG(ZONE_ENUM, (TEXT("PCIBUS!RegMatch RegEnum = %d\r\n"), RegEnum));

        // Get sub-key according to RegEnum
        ValLen = sizeof(DevName) / sizeof(WCHAR);
        status = RegEnumKeyEx(Key, RegEnum, DevName, &ValLen, NULL, NULL, NULL, NULL);

        if (status != ERROR_SUCCESS) {
            DEBUGMSG(ZONE_ENUM, (TEXT("PCIBUS!RegMatch RegEnumKeyEx(%d) returned %d\r\n"), RegEnum, status));
            break;
        }

        Match = RegMatchOne(pInfo, Key, DevName);
        
        if (Match > BestMatch) {
            BestMatch = Match;
            
            // There is at least a partial match, construct path to device key
            wcscpy(RegPath, pInfo->RegPath);
            wcscat(RegPath, TEXT("\\"));
            wcscat(RegPath, DevName);
        }
    }

    RegCloseKey(Key);

    wcscpy(pInfo->RegPath, RegPath);
    
    return BestMatch;
}


//
// Copy registry information for device from template key to instance key.  Write device-specific information
// to instance key.
//
static BOOL
RegCopy(
    PPCI_DEV_INFO pInfo
    )
{
    HKEY TKey;
    HKEY IKey;
    DWORD status;
    DWORD ValType;
    DWORD ValLen;
    DWORD Index;
    DWORD Disposition;
    WCHAR InstKeyPath[DEVKEY_LEN];
    WCHAR IndexStr[DEVKEY_LEN];
    PWCHAR KeyPtr;
    PWCHAR TmpKeyPtr;
    INTERFACE_TYPE IfcType = PCIBus;
    DWORD Irq, Pin, SysIntr;
    BOOL RetVal = TRUE;
    
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!RegCopy+(%s, %d, %d, %d)\r\n", pInfo->RegPath, pInfo->Bus, pInfo->Device, pInfo->Function));

    //
    // Open Template key
    //
    status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, pInfo->RegPath, 0, 0, &TKey);            
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegCopy RegOpenKeyEx(%s) returned %d.\r\n", pInfo->RegPath, status));
        return FALSE;
    }

    // If InstanceIndex value exists, read it
    ValLen = sizeof(Index);
    status = RegQueryValueEx(TKey, PCIBUS_INSTANCEINDEX_VALNAME, NULL, &ValType, (PUCHAR)&Index, &ValLen);             
    if (status != ERROR_SUCCESS) {
        // No InstanceIndex found, start with 1
        Index = 1;
    } else {
        // InstanceIndex value found, increment
        Index++;
    }

    // Write new InstanceIndex value
    status = RegSetValueEx(TKey, PCIBUS_INSTANCEINDEX_VALNAME, 0, PCIBUS_INSTANCEINDEX_VALTYPE, (PUCHAR)&Index, sizeof(Index));
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegCopy RegSetValueEx(%s\\%s) returned %d.\r\n",
            pInfo->RegPath, PCIBUS_INSTANCEINDEX_VALNAME, status));

        RetVal = FALSE;
        goto rc_Close_TKey;
    }
    
    //
    // Construct Instance key name
    //

    // Find last occurence of "Template" in key
    KeyPtr = NULL;
    TmpKeyPtr = wcsstr(pInfo->RegPath, PCIBUS_TEMPLATE_KEYNAME);
    while (TmpKeyPtr != NULL) {
        KeyPtr = TmpKeyPtr;
        TmpKeyPtr += wcslen(PCIBUS_TEMPLATE_KEYNAME);
        TmpKeyPtr = wcsstr(TmpKeyPtr, PCIBUS_TEMPLATE_KEYNAME);
    };
    
    if (KeyPtr == NULL) {
        // Template key didn't have the word Template in it, report error
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegCopy Key %s doesn't contain %s.\r\n",
            pInfo->RegPath, PCIBUS_TEMPLATE_KEYNAME));

        RetVal = FALSE;
        goto rc_Close_TKey;
    }

    wcscpy(InstKeyPath, pInfo->RegPath);
    *(InstKeyPath + (KeyPtr - pInfo->RegPath)) = (WCHAR)'\0';
    wcscat(InstKeyPath, PCIBUS_INSTANCE_KEYNAME);
    wcscat(InstKeyPath, (PWCHAR)(KeyPtr + wcslen(PCIBUS_TEMPLATE_KEYNAME)));
    wsprintf(IndexStr, L"%d", Index);

    if (wcslen(InstKeyPath) + wcslen(IndexStr) >= DEVKEY_LEN) {
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegCopy Error: Created instance key '%s%s' exceeds %d character limit\r\n", InstKeyPath, IndexStr, DEVKEY_LEN - 1));
        RetVal = FALSE;
        goto rc_Close_TKey;
    }

    wcscat(InstKeyPath, IndexStr);

    DEBUGMSG(ZONE_ENUM, (L"PCIbus!RegCopy Instance Key = '%s'\r\n", InstKeyPath));

    // Create/open Instance key
    status = RegCreateKeyEx(HKEY_LOCAL_MACHINE, InstKeyPath, 0, NULL, 0, 0, NULL, &IKey, &Disposition);
                
    if (status != ERROR_SUCCESS) {
        DEBUGMSG(ZONE_ENUM|ZONE_ERROR, (L"PCIBUS!RegCopy RegCreateKeyEx(%s) returned %d.\r\n",
            InstKeyPath, status));

        RetVal = FALSE;
        goto rc_Close_TKey;
    }

    //
    // Copy Template values to Instance values, without overwriting them
    //
    if (RegCopyKey(TKey, IKey) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }
    
    // Set device-specific indentifier information
    if (RegSetVal(IKey, PCIBUS_CLASS_VALNAME, PCIBUS_CLASS_VALTYPE, (PBYTE)&pInfo->Cfg->BaseClass, sizeof(pInfo->Cfg->BaseClass)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_SUBCLASS_VALNAME, PCIBUS_SUBCLASS_VALTYPE, (PBYTE)&pInfo->Cfg->SubClass, sizeof(pInfo->Cfg->SubClass)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_PROGIF_VALNAME, PCIBUS_PROGIF_VALTYPE, (PBYTE)&pInfo->Cfg->ProgIf, sizeof(pInfo->Cfg->ProgIf)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_VENDORID_VALNAME, PCIBUS_VENDORID_VALTYPE, (PBYTE)&pInfo->Cfg->VendorID, sizeof(pInfo->Cfg->VendorID)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_DEVICEID_VALNAME, PCIBUS_DEVICEID_VALTYPE, (PBYTE)&pInfo->Cfg->DeviceID, sizeof(pInfo->Cfg->DeviceID)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_REVISIONID_VALNAME, PCIBUS_REVISIONID_VALTYPE, (PBYTE)&pInfo->Cfg->RevisionID, sizeof(pInfo->Cfg->RevisionID)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    switch (pInfo->Cfg->HeaderType & ~PCI_MULTIFUNCTION) {
    case PCI_DEVICE_TYPE:
        if (RegSetVal(IKey, PCIBUS_SUBVENDORID_VALNAME, PCIBUS_SUBVENDORID_VALTYPE, (PBYTE)&pInfo->Cfg->u.type0.SubVendorID, sizeof(pInfo->Cfg->u.type0.SubVendorID)) == FALSE) {
            RetVal = FALSE;
            goto rc_Close_IKey;
        }

        if (RegSetVal(IKey, PCIBUS_SUBSYSTEMID_VALNAME, PCIBUS_SUBSYSTEMID_VALTYPE, (PBYTE)&pInfo->Cfg->u.type0.SubSystemID, sizeof(pInfo->Cfg->u.type0.SubSystemID)) == FALSE) {
            RetVal = FALSE;
            goto rc_Close_IKey;
        }

        break;
        
    case PCI_BRIDGE_TYPE:
        break;
        
    case PCI_CARDBUS_TYPE:
        if (RegSetVal(IKey, PCIBUS_SUBVENDORID_VALNAME, PCIBUS_SUBVENDORID_VALTYPE, (PBYTE)&pInfo->Cfg->u.type2.SubVendorID, sizeof(pInfo->Cfg->u.type2.SubVendorID)) == FALSE) {
            RetVal = FALSE;
            goto rc_Close_IKey;
        }

        if (RegSetVal(IKey, PCIBUS_SUBSYSTEMID_VALNAME, PCIBUS_SUBSYSTEMID_VALTYPE, (PBYTE)&pInfo->Cfg->u.type2.SubSystemID, sizeof(pInfo->Cfg->u.type2.SubSystemID)) == FALSE) {
            RetVal = FALSE;
            goto rc_Close_IKey;
        }
        
        break;
        
    default:
        break;
    }

    // Set device location information: interface type (PCI) and bus, device and function numbers
    if (RegSetVal(IKey, PCIBUS_IFCTYPE_VALNAME, PCIBUS_IFCTYPE_VALTYPE, (PBYTE)&IfcType, sizeof(IfcType)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_BUSNUMBER_VALNAME, PCIBUS_BUSNUMBER_VALTYPE, (PBYTE)&pInfo->Bus, sizeof(pInfo->Bus)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_DEVICENUMBER_VALNAME, PCIBUS_DEVICENUMBER_VALTYPE, (PBYTE)&pInfo->Device, sizeof(pInfo->Device)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (RegSetVal(IKey, PCIBUS_FUNCTIONNUMBER_VALNAME, PCIBUS_FUNCTIONNUMBER_VALTYPE, (PBYTE)&pInfo->Function, sizeof(pInfo->Function)) == FALSE) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }
    
    // Set Memory Base and Length values
    if (!RegSetList(IKey, PCIBUS_MEMBASE_VALNAME, pInfo->MemBase.Num, pInfo->MemBase.Reg)) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (!RegSetList(IKey, PCIBUS_MEMLEN_VALNAME, pInfo->MemLen.Num, pInfo->MemLen.Reg)) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }
    
    // Set I/O Base and Length values
    if (!RegSetList(IKey, PCIBUS_IOBASE_VALNAME, pInfo->IoBase.Num, pInfo->IoBase.Reg)) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    if (!RegSetList(IKey, PCIBUS_IOLEN_VALNAME, pInfo->IoLen.Num, pInfo->IoLen.Reg)) {
        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    // Get IRQ and interrupt pin
    switch (pInfo->Cfg->HeaderType & ~PCI_MULTIFUNCTION) {   
    case PCI_DEVICE_TYPE: // Devices
        Irq = pInfo->Cfg->u.type0.InterruptLine;
        Pin = pInfo->Cfg->u.type0.InterruptPin;
        break;

    case PCI_BRIDGE_TYPE: // PCI-PCI bridge
        Irq = pInfo->Cfg->u.type1.InterruptLine;
        Pin = pInfo->Cfg->u.type1.InterruptPin;
        break;

    case PCI_CARDBUS_TYPE: // PCI-Cardbus bridge
        Irq = pInfo->Cfg->u.type2.InterruptLine;
        Pin = pInfo->Cfg->u.type2.InterruptPin;
        break;

    default:
        DEBUGMSG(ZONE_ERROR, (L"PCIbus!RegCopy ERROR: invalid header type %d detected.\r\n", pInfo->Cfg->HeaderType));

        RetVal = FALSE;
        goto rc_Close_IKey;
    }

    // If Interrupt Pin register is 0, or if there is an invalid Interrupt Line value, there is no Irq
    if (!((Pin == 0) || (Irq == 0) || (Irq == 0xFF))) {      
        // Write Irq value
        if (RegSetVal(IKey, PCIBUS_IRQ_VALNAME, PCIBUS_IRQ_VALTYPE, (PBYTE)&Irq, sizeof(Irq)) == FALSE) {
            RetVal = FALSE;
            goto rc_Close_IKey;
        }

        // If driver not to be loaded (or will be unloaded immediately), don't request SysIntr
        if (!(pInfo->DevFlags & (DEVFLAGS_NOLOAD | DEVFLAGS_UNLOAD))) {
            // Request new SysIntr from Irq value
            if (RequestSysIntr(Irq, &SysIntr) == FALSE) {
                RetVal = FALSE;
                goto rc_Close_IKey;
            }

            // Write SysIntr value
            if (RegSetVal(IKey, PCIBUS_SYSINTR_VALNAME, PCIBUS_SYSINTR_VALTYPE, (PBYTE)&SysIntr, sizeof(SysIntr)) == FALSE) {
                RetVal = FALSE;
                goto rc_Close_IKey;
            }
        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -