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

📄 pcicfg.c

📁 PCI总线的驱动程序
💻 C
📖 第 1 页 / 共 5 页
字号:
            }
        } 
    }

    PCIRsrc_DelList(BusHead);
    
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCICfgAllocateMemSpace-(Bus %d)\r\n", Bus));
    
    return TRUE;
}


//
// Find match for device in registry
//
static BOOL
PCICfgFindMatch(
    PPCI_DEV_INFO pInfo
    )
{
    WCHAR SavePath[DEVKEY_LEN];

    // Save off registry path
    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) {
        // Exact instance match found
        DEBUGMSG(ZONE_INIT, (L"PCIBUS!PCICfgFindMatch: Matched device %d/%d/%d with registry key '%s'\r\n",
            pInfo->Bus, pInfo->Device, pInfo->Function, pInfo->RegPath));

        return TRUE;
    }

    // Fail if key name too long
    if (wcslen(SavePath) + wcslen(L"\\") + wcslen(PCIBUS_TEMPLATE_KEYNAME) >= DEVKEY_LEN) {
        wcscpy(pInfo->RegPath, SavePath);
        return FALSE;
    }
    
    // No exact instance match found, check for match under Template key
    wcscpy(pInfo->RegPath, SavePath);
    wcscat(pInfo->RegPath, L"\\");
    wcscat(pInfo->RegPath, PCIBUS_TEMPLATE_KEYNAME);
            
    if (RegMatch(pInfo) != PCIBUS_MATCH_NONE) {
        // Partial template match found
        DEBUGMSG(ZONE_INIT, (L"PCIBUS!PCICfgFindMatch: Matched device %d/%d/%d with registry key '%s'\r\n",
            pInfo->Bus, pInfo->Device, pInfo->Function, pInfo->RegPath));

        return TRUE;
    }

    // No match found
    wcscpy(pInfo->RegPath, SavePath);
    return FALSE;
}


//
// Request IRQ from OAL
//
static BOOL
RequestIrq(
    PDEVICE_LOCATION pDevLoc,
    PDWORD pIrq
    )
{
    return KernelIoControl(IOCTL_HAL_REQUEST_IRQ, pDevLoc, sizeof(*pDevLoc), pIrq, sizeof(*pIrq), NULL);
}


//
// Read Base Address Registers and size, populate Info struct with this information
//
static BOOL
PCIReadBARs(
    PPCI_DEV_INFO pInfo
    )
{   
    DWORD NumberOfRegs;
    DWORD Offset;
    DWORD i;
    DWORD BaseAddress;
    DWORD Size;
    DWORD Reg;
    DWORD IoIndex = 0;
    DWORD MemIndex = 0;

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

    // Determine number of BARs to examine from header type
    switch (pInfo->Cfg->HeaderType & ~PCI_MULTIFUNCTION) {
    case PCI_DEVICE_TYPE:
        NumberOfRegs = PCI_TYPE0_ADDRESSES;
        break;

    case PCI_BRIDGE_TYPE:
        NumberOfRegs = PCI_TYPE1_ADDRESSES;
        break;

    case PCI_CARDBUS_TYPE:
        NumberOfRegs = PCI_TYPE2_ADDRESSES;
        break;

    default:
        return FALSE;
    }
        
    for (i = 0, Offset = 0x10; i < NumberOfRegs; i++, Offset += 4) {
        // Get base address register value
        Reg = pInfo->Cfg->u.type0.BaseAddresses[i];

        // Get size info
        PCIConfig_Write(pInfo->Bus, pInfo->Device, pInfo->Function, Offset, 0xFFFFFFFF);
        BaseAddress = PCIConfig_Read(pInfo->Bus, pInfo->Device, pInfo->Function, Offset);
        PCIConfig_Write(pInfo->Bus, pInfo->Device, pInfo->Function, Offset, Reg);
       
        if (Reg & PCI_ADDRESS_IO_SPACE) {
            // IO space
            // Re-adjust BaseAddress if upper 16-bits are 0 (this is allowable in PCI 2.2 spec)
            if (((BaseAddress & PCI_ADDRESS_IO_ADDRESS_MASK) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
                BaseAddress |= 0xFFFF0000;
            }
            
            Size = ~(BaseAddress & PCI_ADDRESS_IO_ADDRESS_MASK);

            if ((BaseAddress != 0) && (BaseAddress != 0xFFFFFFFF) && (((Size + 1) & Size) == 0)) {
                // BAR has valid format (consecutive high 1's and consecutive low 0's)
                pInfo->IoLen.Reg[IoIndex] = Size + 1;
                pInfo->IoLen.Num++;
                pInfo->IoBase.Reg[IoIndex++] = Reg & PCI_ADDRESS_IO_ADDRESS_MASK;
                pInfo->IoBase.Num++;
            } else {
                // BAR invalid => skip to next one
                continue;
            }
        } else {
            // Memory space
            if ((Reg & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT) {
                // PCI 2.2 spec no longer supports this type of memory addressing
                DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIReadBARs: 20-bit addressing not supported\r\n"));
                return FALSE;
            }
            
            // Re-adjust BaseAddress if upper 16-bits are 0 (this is allowable in PCI 2.2 spec)
            if (((BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK) != 0) && ((BaseAddress & 0xFFFF0000) == 0)) {
                BaseAddress |= 0xFFFF0000;
            }
            
            Size = ~(BaseAddress & PCI_ADDRESS_MEMORY_ADDRESS_MASK);

            if ((BaseAddress != 0) && (BaseAddress != 0xFFFFFFFF) && (((Size + 1) & Size) == 0)) {
                // BAR has valid format (consecutive high 1's and consecutive low 0's)
                pInfo->MemLen.Reg[MemIndex] = Size + 1;
                pInfo->MemLen.Num++;
                pInfo->MemBase.Reg[MemIndex++] = Reg & PCI_ADDRESS_MEMORY_ADDRESS_MASK;
                pInfo->MemBase.Num++;
            } else {
                // BAR invalid => skip to next one
                continue;
            }

            if ((Reg & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT) {
                // 64 bit device - BAR is twice as wide, skip upper 32-bits
                Offset += 4;
                i++;
            }
        }     
    }

    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIReadBARs-\r\n"));

    return TRUE;
}


//
// Retrieve Base Address Register information from device
//
BOOL
PCIGetBARs(
    PPCI_DEV_INFO pInfo
    )
{
    WCHAR SavePath[DEVKEY_LEN];
    BOOL RetVal = TRUE;
    
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIGetBARs+(Bus %d, Device %d, Function %d)\r\n",
        pInfo->Bus, pInfo->Device, pInfo->Function));

    // Save off registry path
    wcsncpy(SavePath, pInfo->RegPath, DEVKEY_LEN - 1);
    SavePath[DEVKEY_LEN - 1] = L'\0';    // make sure longest string is terminated
    
    // Attempt to find match for this device in the registry and get info
    if (PCICfgFindMatch(pInfo)) {
        if (!RegGetInfo(pInfo)) {
            RetVal = FALSE;
            goto PCIGetBARs_Exit;
        }

        if (!pInfo->Configure) {
            goto PCIGetBARs_Exit;
        }
        
        // Make sure the sum of Base entries is less than or equal to 6
        if (pInfo->MemBase.Num + pInfo->IoBase.Num > PCI_TYPE0_ADDRESSES) {
            DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIGetBARs: The number of registry values '%s' and '%s' under '%s'  must sum to be less than %d.\r\n",
                pInfo->RegPath, PCIBUS_MEMBASE_VALNAME, PCIBUS_IOBASE_VALNAME, PCI_TYPE0_ADDRESSES));

            RetVal = FALSE;
            goto PCIGetBARs_Exit;
        }

        // Make sure the sum of Len entries is less than or equal to 6
        if (pInfo->MemLen.Num + pInfo->IoLen.Num > PCI_TYPE0_ADDRESSES) {
            DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIGetBARs: The number of registry values '%s' and '%s' under '%s'  must sum to be less than %d.\r\n",
                pInfo->RegPath, PCIBUS_MEMLEN_VALNAME, PCIBUS_IOLEN_VALNAME, PCI_TYPE0_ADDRESSES));

            RetVal = FALSE;
            goto PCIGetBARs_Exit;
        }

        if (pInfo->MemLen.Num + pInfo->IoLen.Num > 0) {
            // If there is any Length info, return
            goto PCIGetBARs_Exit;
        }
    }

    // If ConfigEntry point defined, call it to determine BAR lengths
    if (pInfo->ConfigEntry) {
        DWORD Status;
        
        // Load driver Dll and obtain ConfigEntry function address
        if (!LoadConfigEntry(pInfo)) {
            DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIGetBARs: Failed LoadConfigEntry call\r\n"));
            RetVal = FALSE;
            goto PCIGetBARs_Exit;
        }
        
        Status = ((PFN_CONFIGENTRY)(pInfo->ConfigInfo->ConfigEntryFn))(PCIBUS_CONFIG_SIZE, pInfo, NULL, NULL, NULL, NULL);

        // Unload Dll
        UnloadConfigEntrys( );    
        
        if (Status != ERROR_SUCCESS) {
            if (Status == ERROR_NOT_SUPPORTED) {
                // ConfigEntry point doesn't support this type of call, so do it here
                // Read the base address registers to determine BAR lengths
                if (!PCIReadBARs(pInfo)) {
                    DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIGetBARs: Failed PCIReadBARs call\r\n"));
                    
                    RetVal = FALSE;
                }
            } else {
                DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIGetBARs: Failed ConfigEntry call\r\n"));

                RetVal = FALSE;
            }
        }
    } else {
        // Read the base address registers to determine BAR lengths
        if (!PCIReadBARs(pInfo)) {
            DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIGetBARs: Failed PCIReadBARs call\r\n"));
            
            RetVal = FALSE;
        }
    }

PCIGetBARs_Exit:
    // Restore path
    wcscpy(pInfo->RegPath, SavePath);
    
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIGetBARs-\r\n"));
        
    return RetVal;
}


//
// Call device configuration routine with INIT parameter, if it exists
//
BOOL
PCIInitDevice(
    PPCI_DEV_INFO pInfo
    )
{
    DWORD Status;
    
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIInitDevice+(Bus %d, Device %d, Function %d)\r\n",
        pInfo->Bus, pInfo->Device, pInfo->Function));
    
    // If ConfigEntry point not defined, do nothing
    if (!pInfo->ConfigEntry) return TRUE;
    
    // Load driver Dll and obtain ConfigEntry function address
    if (!LoadConfigEntry(pInfo)) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIInitDevice: Failed LoadConfigEntry call\r\n"));
        return FALSE;
    }
        
    Status = ((PFN_CONFIGENTRY)(pInfo->ConfigInfo->ConfigEntryFn))(PCIBUS_CONFIG_INIT, pInfo, NULL, NULL, NULL, NULL);

    // Unload Dll
    UnloadConfigEntrys( );    
        
    if ((Status != ERROR_SUCCESS) && (Status != ERROR_NOT_SUPPORTED)) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCIInitDevice: Failed ConfigEntry(PCIBUS_CONFIG_INIT) call\r\n"));
        return FALSE;
    }

    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCIInitDevice-\r\n"));
    
    return TRUE;
}

⌨️ 快捷键说明

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