📄 pcicfg.c
字号:
// 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 + -