📄 pci.c
字号:
}
/* Now we still have something to copy */
if (Length)
{
/* Check if it's vendor-specific data */
if (Offset >= PCI_COMMON_HDR_LENGTH)
{
/* Read it now */
HalpWritePCIConfig(BusHandler, Slot, Buffer, Offset, Length);
Len += Length;
}
}
/* Update the total length read */
return Len;
}
NTSTATUS
NTAPI
HalpSetupPciDeviceForDebugging(IN PVOID LoaderBlock,
IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
{
DPRINT1("Unimplemented!\n");
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
HalpReleasePciDeviceForDebugging(IN OUT PDEBUG_DEVICE_DESCRIPTOR PciDevice)
{
DPRINT1("Unimplemented!\n");
return STATUS_NOT_IMPLEMENTED;
}
static ULONG STDCALL
PciSize(ULONG Base, ULONG Mask)
{
ULONG Size = Mask & Base; /* Find the significant bits */
Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
return Size;
}
NTSTATUS
NTAPI
HalpAssignPCISlotResources(IN PBUS_HANDLER BusHandler,
IN PBUS_HANDLER RootHandler,
IN PUNICODE_STRING RegistryPath,
IN PUNICODE_STRING DriverClassName OPTIONAL,
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
IN ULONG Slot,
IN OUT PCM_RESOURCE_LIST *AllocatedResources)
{
PCI_COMMON_CONFIG PciConfig;
SIZE_T Address;
SIZE_T ResourceCount;
ULONG Size[PCI_TYPE0_ADDRESSES];
NTSTATUS Status = STATUS_SUCCESS;
UCHAR Offset;
PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
PCI_SLOT_NUMBER SlotNumber;
ULONG WriteBuffer;
/* FIXME: Should handle 64-bit addresses */
/* Read configuration data */
SlotNumber.u.AsULONG = Slot;
HalpReadPCIConfig(BusHandler, SlotNumber, &PciConfig, 0, PCI_COMMON_HDR_LENGTH);
/* Check if we read it correctly */
if (PciConfig.VendorID == PCI_INVALID_VENDORID)
return STATUS_NO_SUCH_DEVICE;
/* Read the PCI configuration space for the device and store base address and
size information in temporary storage. Count the number of valid base addresses */
ResourceCount = 0;
for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
{
if (0xffffffff == PciConfig.u.type0.BaseAddresses[Address])
PciConfig.u.type0.BaseAddresses[Address] = 0;
/* Memory resource */
if (0 != PciConfig.u.type0.BaseAddresses[Address])
{
ResourceCount++;
Offset = FIELD_OFFSET(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
/* Write 0xFFFFFFFF there */
WriteBuffer = 0xffffffff;
HalpWritePCIConfig(BusHandler, SlotNumber, &WriteBuffer, Offset, sizeof(ULONG));
/* Read that figure back from the config space */
HalpReadPCIConfig(BusHandler, SlotNumber, &Size[Address], Offset, sizeof(ULONG));
/* Write back initial value */
HalpWritePCIConfig(BusHandler, SlotNumber, &PciConfig.u.type0.BaseAddresses[Address], Offset, sizeof(ULONG));
}
}
/* Interrupt resource */
if (0 != PciConfig.u.type0.InterruptLine)
ResourceCount++;
/* Allocate output buffer and initialize */
*AllocatedResources = ExAllocatePoolWithTag(
PagedPool,
sizeof(CM_RESOURCE_LIST) +
(ResourceCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
TAG('H','a','l',' '));
if (NULL == *AllocatedResources)
return STATUS_NO_MEMORY;
(*AllocatedResources)->Count = 1;
(*AllocatedResources)->List[0].InterfaceType = PCIBus;
(*AllocatedResources)->List[0].BusNumber = BusHandler->BusNumber;
(*AllocatedResources)->List[0].PartialResourceList.Version = 1;
(*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
(*AllocatedResources)->List[0].PartialResourceList.Count = ResourceCount;
Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
/* Store configuration information */
for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
{
if (0 != PciConfig.u.type0.BaseAddresses[Address])
{
if (/*PCI_BASE_ADDRESS_SPACE_MEMORY*/ 0 ==
(PciConfig.u.type0.BaseAddresses[Address] & 0x1))
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */
Descriptor->u.Memory.Start.QuadPart = (PciConfig.u.type0.BaseAddresses[Address] & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_ADDRESS_MEMORY_ADDRESS_MASK);
}
else if (PCI_ADDRESS_IO_SPACE ==
(PciConfig.u.type0.BaseAddresses[Address] & 0x1))
{
Descriptor->Type = CmResourceTypePort;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */
Descriptor->u.Port.Start.QuadPart = PciConfig.u.type0.BaseAddresses[Address] &= PCI_ADDRESS_IO_ADDRESS_MASK;
Descriptor->u.Port.Length = PciSize(Size[Address], PCI_ADDRESS_IO_ADDRESS_MASK & 0xffff);
}
else
{
ASSERT(FALSE);
return STATUS_UNSUCCESSFUL;
}
Descriptor++;
}
}
if (0 != PciConfig.u.type0.InterruptLine)
{
Descriptor->Type = CmResourceTypeInterrupt;
Descriptor->ShareDisposition = CmResourceShareShared; /* FIXME Just a guess */
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE; /* FIXME Just a guess */
Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
Descriptor++;
}
ASSERT(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + ResourceCount);
/* FIXME: Should store the resources in the registry resource map */
return Status;
}
ULONG
NTAPI
HaliPciInterfaceReadConfig(IN PBUS_HANDLER RootBusHandler,
IN ULONG BusNumber,
IN PCI_SLOT_NUMBER SlotNumber,
IN PVOID Buffer,
IN ULONG Offset,
IN ULONG Length)
{
BUS_HANDLER BusHandler;
PPCI_COMMON_CONFIG PciData = (PPCI_COMMON_CONFIG)Buffer;
/* Setup fake PCI Bus handler */
RtlCopyMemory(&BusHandler, &HalpFakePciBusHandler, sizeof(BUS_HANDLER));
BusHandler.BusNumber = BusNumber;
/* Read configuration data */
HalpReadPCIConfig(&BusHandler, SlotNumber, Buffer, Offset, Length);
/* Check if caller only wanted at least Vendor ID */
if (Length >= 2)
{
/* Validate it */
if (PciData->VendorID != PCI_INVALID_VENDORID)
{
/* Check if this is the new maximum bus number */
if (HalpMaxPciBus < BusHandler.BusNumber)
{
/* Set it */
HalpMaxPciBus = BusHandler.BusNumber;
}
}
}
/* Return length */
return Length;
}
PPCI_REGISTRY_INFO_INTERNAL
NTAPI
HalpQueryPciRegistryInfo(VOID)
{
WCHAR NameBuffer[8];
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName, ConfigName, IdentName;
HANDLE KeyHandle, BusKeyHandle;
NTSTATUS Status;
UCHAR KeyBuffer[sizeof(PPCI_REGISTRY_INFO) + 100];
PKEY_VALUE_FULL_INFORMATION ValueInfo = (PVOID)KeyBuffer;
ULONG ResultLength;
PWSTR Tag;
ULONG i;
PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
PPCI_REGISTRY_INFO PciRegInfo;
PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
/* Setup the object attributes for the key */
RtlInitUnicodeString(&KeyName,
L"\\Registry\\Machine\\Hardware\\Description\\"
L"System\\MultiFunctionAdapter");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
/* Open the key */
Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status)) return NULL;
/* Setup the receiving string */
KeyName.Buffer = NameBuffer;
KeyName.MaximumLength = sizeof(NameBuffer);
/* Setup the configuration and identifier key names */
RtlInitUnicodeString(&ConfigName, L"ConfigurationData");
RtlInitUnicodeString(&IdentName, L"Identifier");
/* Keep looping for each ID */
for (i = 0; TRUE; i++)
{
/* Setup the key name */
RtlIntegerToUnicodeString(i, 10, &KeyName);
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
OBJ_CASE_INSENSITIVE,
KeyHandle,
NULL);
/* Open it */
Status = ZwOpenKey(&BusKeyHandle, KEY_READ, &ObjectAttributes);
if (!NT_SUCCESS(Status))
{
/* None left, fail */
ZwClose(KeyHandle);
return NULL;
}
/* Read the registry data */
Status = ZwQueryValueKey(BusKeyHandle,
&IdentName,
KeyValueFullInformation,
ValueInfo,
sizeof(KeyBuffer),
&ResultLength);
if (!NT_SUCCESS(Status))
{
/* Failed, try the next one */
ZwClose(BusKeyHandle);
continue;
}
/* Get the PCI Tag and validate it */
Tag = (PWSTR)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
if ((Tag[0] != L'P') ||
(Tag[1] != L'C') ||
(Tag[2] != L'I') ||
(Tag[3]))
{
/* Not a valid PCI entry, skip it */
ZwClose(BusKeyHandle);
continue;
}
/* Now read our PCI structure */
Status = ZwQueryValueKey(BusKeyHandle,
&ConfigName,
KeyValueFullInformation,
ValueInfo,
sizeof(KeyBuffer),
&ResultLength);
ZwClose(BusKeyHandle);
if (!NT_SUCCESS(Status)) continue;
/* We read it OK! Get the actual resource descriptors */
FullDescriptor = (PCM_FULL_RESOURCE_DESCRIPTOR)
((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
PartialDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)
((ULONG_PTR)FullDescriptor->
PartialResourceList.PartialDescriptors);
/* Check if this is our PCI Registry Information */
if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
{
/* Close the key */
ZwClose(KeyHandle);
/* FIXME: Check PnP\PCI\CardList */
/* Get the PCI information */
PciRegInfo = (PPCI_REGISTRY_INFO)(PartialDescriptor + 1);
/* Allocate the return structure */
PciRegistryInfo = ExAllocatePoolWithTag(NonPagedPool,
sizeof(PCI_REGISTRY_INFO_INTERNAL),
TAG('H', 'a', 'l', ' '));
if (!PciRegistryInfo) return NULL;
/* Fill it out */
PciRegistryInfo->HardwareMechanism = PciRegInfo->HardwareMechanism;
PciRegistryInfo->NoBuses = PciRegInfo->NoBuses;
PciRegistryInfo->MajorRevision = PciRegInfo->MajorRevision;
PciRegistryInfo->MinorRevision = PciRegInfo->MinorRevision;
PciRegistryInfo->ElementCount = 0;
}
}
}
VOID
NTAPI
HalpInitializePciStubs(VOID)
{
PPCI_REGISTRY_INFO_INTERNAL PciRegistryInfo;
UCHAR PciType;
PPCIPBUSDATA BusData = (PPCIPBUSDATA)HalpFakePciBusHandler.BusData;
ULONG i;
PCI_SLOT_NUMBER j;
ULONG VendorId = 0;
/* Query registry information */
PciRegistryInfo = HalpQueryPciRegistryInfo();
if (!PciRegistryInfo)
{
/* Assume type 1 */
PciType = 1;
}
else
{
/* Get the type and free the info structure */
PciType = PciRegistryInfo->HardwareMechanism & 0xF;
ExFreePool(PciRegistryInfo);
}
/* Initialize the PCI lock */
KeInitializeSpinLock(&HalpPCIConfigLock);
/* Check the type of PCI bus */
switch (PciType)
{
/* Type 1 PCI Bus */
case 1:
/* Copy the Type 1 handler data */
RtlCopyMemory(&PCIConfigHandler,
&PCIConfigHandlerType1,
sizeof(PCIConfigHandler));
/* Set correct I/O Ports */
BusData->Config.Type1.Address = PCI_TYPE1_ADDRESS_PORT;
BusData->Config.Type1.Data = PCI_TYPE1_DATA_PORT;
break;
/* Type 2 PCI Bus */
case 2:
/* Copy the Type 1 handler data */
RtlCopyMemory(&PCIConfigHandler,
&PCIConfigHandlerType2,
sizeof (PCIConfigHandler));
/* Set correct I/O Ports */
BusData->Config.Type2.CSE = PCI_TYPE2_CSE_PORT;
BusData->Config.Type2.Forward = PCI_TYPE2_FORWARD_PORT;
BusData->Config.Type2.Base = PCI_TYPE2_ADDRESS_BASE;
/* Only 16 devices supported, not 32 */
BusData->MaxDevice = 16;
break;
default:
/* Invalid type */
DbgPrint("HAL: Unnkown PCI type\n");
}
/* Loop all possible buses */
for (i = 0; i < 256; i++)
{
/* Loop all devices */
for (j.u.AsULONG = 0; j.u.AsULONG < 32; j.u.AsULONG++)
{
/* Query the interface */
if (HaliPciInterfaceReadConfig(NULL,
i,
j,
&VendorId,
0,
sizeof(ULONG)))
{
/* Validate the vendor ID */
if ((USHORT)VendorId != PCI_INVALID_VENDORID)
{
/* Set this as the maximum ID */
HalpMaxPciBus = i;
break;
}
}
}
}
/* We're done */
HalpPCIConfigInitialized = TRUE;
}
VOID
NTAPI
HalpInitializePciBus(VOID)
{
/* Initialize the stubs */
HalpInitializePciStubs();
/* FIXME: Initialize NMI Crash Flag */
}
/* EOF */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -