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

📄 pcicfg.c

📁 WINCE5.0操作系统下的PCI总线驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
            // If 32-bit I/O, set the I/O limit & base upper address registers.
            if (Use32bitIo) {
                DEBUGMSG(ZONE_INIT, (L"PCIBUS!PCI-PCI bridge %d/%d/%d supports 32-bit I/O\r\n", Rsrc->Bus, Rsrc->Device, Rsrc->Function));
                DEBUGMSG(1, (L"IoBase = 0x%X, IoLimit = 0x%X\r\n", Rsrc->Base, Rsrc->Base + Rsrc->Size - 1));
                IoBase = (Rsrc->Base + Rsrc->Size - 1) & 0xFFFF0000;
                IoBase |= (Rsrc->Base) >> 16;
                DEBUGMSG(1, (L"IoBase reg = 0x%X, offset 0x%X\r\n", IoBase, PCIBRIDGE_IO_UPPER16));
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCIBRIDGE_IO_UPPER16, IoBase);
            }

            // Enable device's I/O space (and bus mastering capability)
            Reg = PCIConfig_Read(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS);
            if ((Reg & (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_IO_SPACE)) != ( PCI_ENABLE_BUS_MASTER | PCI_ENABLE_IO_SPACE)) {
                Reg &= 0x3FF;
                Reg |= PCI_ENABLE_BUS_MASTER | PCI_ENABLE_IO_SPACE;
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS, Reg);  
            }
        } else if (!Rsrc->Placed) {
            // Device
            if (Rsrc->ConfigInfo) {
                // This resource needs to be set by the device's ConfigEntry routine (if supported)
                DWORD Status = ((PFN_CONFIGENTRY)Rsrc->ConfigInfo->ConfigEntryFn)(PCIBUS_CONFIG_SET, NULL, Rsrc, NULL, NULL, NULL);
        
                if (Status != ERROR_SUCCESS) {
                    if (Status == ERROR_NOT_SUPPORTED) {
                        // ConfigEntry point doesn't support this type of call, so do it here
                        // Set device's base address register
                        PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base);
                    } else {
                        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfgAllocIoSpace: Failed ConfigEntry call\r\n"));

                        return FALSE;
                    }
                }
            } else {    
                // Set device's base address register
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base);
            }
            
            // Enable device's I/O space (and bus mastering capability)
            Reg = PCIConfig_Read(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS);
            if ((Reg & (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_IO_SPACE )) != (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_IO_SPACE)) {
                Reg &= 0x3FF;
                Reg |= PCI_ENABLE_BUS_MASTER | PCI_ENABLE_IO_SPACE;
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS, Reg);
            }
        } 
    }

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


//
// For each memory resource, allocate memory space on PCIbus and assign address to BAR
//
static BOOL
PCICfgAllocateMemSpace(
    DWORD Bus,
    DWORD Base,
    DWORD Size
    )
{
    PPCI_RSRC Rsrc, BusHead;
    ULONG MemBase;
    DWORD Reg;
   
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCICfgAllocateMemSpace+(Bus %d, Base 0x%X, Size 0x%X)\r\n", Bus, Base, Size));
    
    // Create bus head node with available address range
    if (!(BusHead = PCIRsrc_New(Bus, 0, 0, 0, Base, Size, TRUE, 0, TRUE, NULL))) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfgAllocateIoSpace: Failed local alloc of BusHead\r\n"));
        return FALSE;
    }

    while (Rsrc = PCIRsrc_GetNext(g_MemHead, Bus)) {
        // Place resource
        if (!PCIRsrc_Place(BusHead, Rsrc)) {
            DEBUGMSG(ZONE_ERROR,
                (L"PCIBUS!PCICfgAllocMemSpace: Failed to place %s resource: Bus %d, Device %d, Function %d\r\n",
                (Rsrc->Bridge) ? L"Bridge" : L"Device", Rsrc->Bus, Rsrc->Device, Rsrc->Function));
                    
            continue;
        }

        DEBUGMSG(ZONE_INIT, (L"PCIBUS!PCICfgAllocMemSpace (%s): Bus %d, Device %d, Function %d, Offset 0x%X, MemBase 0x%X, MemSize 0x%X\r\n",
            (Rsrc->Bridge) ? L"PCI-PCI Bridge" : L"Device", Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base, Rsrc->Size));
                
        if (Rsrc->Bridge) {
            // Allocate resources for bridge's secondary bus
            PCICfgAllocateMemSpace(Rsrc->SecBus, Rsrc->Base, Rsrc->Size);

            // Set bridge's base and limit address registers
            ((PBRIDGE_MEM)(&MemBase))->MemoryLimit.Address = (WORD)(((Rsrc->Base + Rsrc->Size - 1) & 0xFFF00000) >> 20);
            ((PBRIDGE_MEM)(&MemBase))->MemoryBase.Address = (WORD)(((Rsrc->Base) & 0xFFF00000) >> 20);
            PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCIBRIDGE_MEMORY, MemBase);

            // Enable device's memory space (and bus mastering capability)
            Reg = PCIConfig_Read(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS);
            if ((Reg & (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE )) != (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE)) {
                Reg &= 0x3FF;
                Reg |= PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE;
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS, Reg); 
            }
        } else if (!Rsrc->Placed) {
            if (Rsrc->ConfigInfo) {
                // This resource needs to be set by the device's ConfigEntry routine (if supported)
                DWORD Status = ((PFN_CONFIGENTRY)Rsrc->ConfigInfo->ConfigEntryFn)(PCIBUS_CONFIG_SET, NULL, Rsrc, NULL, NULL, NULL);
        
                if (Status != ERROR_SUCCESS) {
                    if (Status == ERROR_NOT_SUPPORTED) {
                        // ConfigEntry point doesn't support this type of call, so do it here
                        // Set device's base address register
                        PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base);
                    } else {
                        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfgAllocMemSpace: Failed ConfigEntry call\r\n"));

                        return FALSE;
                    }
                }
            } else {    
                // Set device's base address register
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base);
            }

            // Enable device's memory space (and bus mastering capability)
            Reg = PCIConfig_Read(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS);
            if ((Reg & (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE)) != (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE)) {
                Reg &= 0x3FF;
                Reg |= PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE;
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS, Reg);
            }
        } 
    }

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

//
// For each prefetch memory resource, allocate memory space on PCIbus and assign address to BAR
//
static BOOL
PCICfgAllocatePrefetchMemSpace(
    DWORD Bus,
    DWORD Base,
    DWORD Size
    )
{
    PPCI_RSRC Rsrc, BusHead;
    ULONG MemBase;
    DWORD Reg;
   
    DEBUGMSG(ZONE_FUNCTION, (L"PCIBUS!PCICfgAllocatePrefetchMemSpace+(Bus %d, Base 0x%X, Size 0x%X)\r\n", Bus, Base, Size));
    
    // Create bus head node with available address range
    if (!(BusHead = PCIRsrc_New(Bus, 0, 0, 0, Base, Size, TRUE, 0, TRUE, NULL))) {
        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfgAllocatePrefetchMemSpace: Failed local alloc of BusHead\r\n"));
        return FALSE;
    }

    while (Rsrc = PCIRsrc_GetNext(g_PrefetchMemHead, Bus)) {
        // Place resource
        if (!PCIRsrc_Place(BusHead, Rsrc)) {
            DEBUGMSG(ZONE_ERROR,
                (L"PCIBUS!PCICfgAllocPrefetchMemSpace: Failed to place %s resource: Bus %d, Device %d, Function %d\r\n",
                (Rsrc->Bridge) ? L"Bridge" : L"Device", Rsrc->Bus, Rsrc->Device, Rsrc->Function));
                    
            continue;
        }

        DEBUGMSG(ZONE_INIT, (L"PCIBUS!PCICfgAllocPrefetchMemSpace (%s): Bus %d, Device %d, Function %d, Offset 0x%X, MemBase 0x%X, MemSize 0x%X\r\n",
            (Rsrc->Bridge) ? L"PCI-PCI Bridge" : L"Device", Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base, Rsrc->Size));
                
        if (Rsrc->Bridge) {
            // Allocate resources for bridge's secondary bus
            PCICfgAllocatePrefetchMemSpace(Rsrc->SecBus, Rsrc->Base, Rsrc->Size);

            // Set bridge's base and limit address registers
            
            ((PBRIDGE_MEM)(&MemBase))->MemoryLimit.Address = (WORD)(((Rsrc->Base + Rsrc->Size - 1) & 0xFFF00000) >> 20);
            ((PBRIDGE_MEM)(&MemBase))->MemoryBase.Address = (WORD)(((Rsrc->Base) & 0xFFF00000) >> 20);
            PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCIBRIDGE_PREFETCHABLE, MemBase);
            PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCIBRIDGE_BASE_UPPER32, 0);
            PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCIBRIDGE_LIMIT_UPPER32,0);

            // Enable device's memory space (and bus mastering capability)
            Reg = PCIConfig_Read(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS);
            if ((Reg & (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE )) != (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE)) {
                Reg &= 0x3FF;
                Reg |= PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE;
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS, Reg); 
            }
        } else if (!Rsrc->Placed) {
            if (Rsrc->ConfigInfo) {
                // This resource needs to be set by the device's ConfigEntry routine (if supported)
                DWORD Status = ((PFN_CONFIGENTRY)Rsrc->ConfigInfo->ConfigEntryFn)(PCIBUS_CONFIG_SET, NULL, Rsrc, NULL, NULL, NULL);
        
                if (Status != ERROR_SUCCESS) {
                    if (Status == ERROR_NOT_SUPPORTED) {
                        // ConfigEntry point doesn't support this type of call, so do it here
                        // Set device's base address register
                        PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base);
                    } else {
                        DEBUGMSG(ZONE_ERROR, (L"PCIBUS!PCICfgAllocMemSpace: Failed ConfigEntry call\r\n"));

                        return FALSE;
                    }
                }
            } else {    
                // Set device's base address register
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, Rsrc->Offset, Rsrc->Base);
            }

            // Enable device's memory space (and bus mastering capability)
            Reg = PCIConfig_Read(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS);
            if ((Reg & (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE)) != (PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE)) {
                Reg &= 0x3FF;
                Reg |= PCI_ENABLE_BUS_MASTER | PCI_ENABLE_MEMORY_SPACE;
                PCIConfig_Write(Rsrc->Bus, Rsrc->Device, Rsrc->Function, PCI_CONFIG_COMMAND_STATUS, Reg);
            }
        } 
    }

    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 %

⌨️ 快捷键说明

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