NTSTATUS NTAPI PciFdoIrpStartDevice(IN PIRP Irp, IN PIO_STACK_LOCATION IoStackLocation, IN PPCI_FDO_EXTENSION DeviceExtension) { NTSTATUS Status; PCM_RESOURCE_LIST Resources; PAGED_CODE(); /* The device stack must be starting the FDO in a success path */ if (!NT_SUCCESS(Irp->IoStatus.Status)) return STATUS_NOT_SUPPORTED; /* Attempt to switch the state machine to the started state */ Status = PciBeginStateTransition(DeviceExtension, PciStarted); if (!NT_SUCCESS(Status)) return Status; /* Check for any boot-provided resources */ Resources = IoStackLocation->Parameters.StartDevice.AllocatedResources; if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) { /* These resources would only be for non-root FDOs, unhandled for now */ ASSERT(Resources->Count == 1); UNIMPLEMENTED_DBGBREAK(); } /* Initialize the arbiter for this FDO */ Status = PciInitializeArbiterRanges(DeviceExtension, Resources); if (!NT_SUCCESS(Status)) { /* Cancel the transition if this failed */ PciCancelStateTransition(DeviceExtension, PciStarted); return Status; } /* Again, check for boot-provided resources for non-root FDO */ if ((Resources) && !(PCI_IS_ROOT_FDO(DeviceExtension))) { /* Unhandled for now */ ASSERT(Resources->Count == 1); UNIMPLEMENTED_DBGBREAK(); } /* Commit the transition to the started state */ PciCommitStateTransition(DeviceExtension, PciStarted); return STATUS_SUCCESS; }
NTSTATUS NTAPI tranirq_Constructor(IN PVOID DeviceExtension, IN PVOID Instance, IN PVOID InterfaceData, IN USHORT Version, IN USHORT Size, IN PINTERFACE Interface) { PPCI_FDO_EXTENSION FdoExtension = (PPCI_FDO_EXTENSION)DeviceExtension; ULONG BaseBus, ParentBus; INTERFACE_TYPE ParentInterface; ASSERT_FDO(FdoExtension); UNREFERENCED_PARAMETER(Instance); UNREFERENCED_PARAMETER(Version); UNREFERENCED_PARAMETER(Size); /* Make sure it's the right resource type */ if ((ULONG)InterfaceData != CmResourceTypeInterrupt) { /* Fail this invalid request */ DPRINT1("PCI - IRQ trans constructor doesn't like %p in InterfaceSpecificData\n", InterfaceData); return STATUS_INVALID_PARAMETER_3; } /* Get the bus, and use this as the interface-specific data */ BaseBus = FdoExtension->BaseBus; InterfaceData = (PVOID)BaseBus; /* Check if this is the root bus */ if (PCI_IS_ROOT_FDO(FdoExtension)) { /* It is, so there is no parent, and it's connected on the system bus */ ParentBus = 0; ParentInterface = Internal; DPRINT1(" Is root FDO\n"); } else { /* It's not, so we have to get the root bus' bus number instead */ #if 0 // when have PDO commit ParentBus = FdoExtension->PhysicalDeviceObject->DeviceExtension->ParentFdoExtension->BaseBus; ParentInterface = PCIBus; DPRINT1(" Is bridge FDO, parent bus %x, secondary bus %x\n", ParentBus, BaseBus); #endif } /* Now call the legacy HAL interface to get the correct translator */ return HalGetInterruptTranslator(ParentInterface, ParentBus, PCIBus, sizeof(TRANSLATOR_INTERFACE), 0, (PTRANSLATOR_INTERFACE)Interface, (PULONG)&InterfaceData); }
NTSTATUS NTAPI PciGetConfigHandlers(IN PPCI_FDO_EXTENSION FdoExtension) { PBUS_HANDLER BusHandler; NTSTATUS Status; ASSERT(FdoExtension->BusHandler == NULL); /* Check if this is the FDO for the root bus */ if (PCI_IS_ROOT_FDO(FdoExtension)) { /* Query the PCI Bus Interface that ACPI exposes */ ASSERT(FdoExtension->PciBusInterface == NULL); Status = PciQueryForPciBusInterface(FdoExtension); if (!NT_SUCCESS(Status)) { /* No ACPI, so Bus Numbers should be maintained by BIOS */ ASSERT(!PciAssignBusNumbers); } else { /* ACPI detected, PCI Bus Driver will reconfigure bus numbers*/ PciAssignBusNumbers = TRUE; } } else { /* Check if the root bus already has the interface set up */ if (FdoExtension->BusRootFdoExtension->PciBusInterface) { /* Nothing for this FDO to do */ return STATUS_SUCCESS; } /* Fail into case below so we can query the HAL interface */ Status = STATUS_NOT_SUPPORTED; } /* If the ACPI PCI Bus Interface couldn't be obtained, try the HAL */ if (!NT_SUCCESS(Status)) { /* Bus number assignment should be static */ ASSERT(Status == STATUS_NOT_SUPPORTED); ASSERT(!PciAssignBusNumbers); /* Call the HAL to obtain the bus handler for PCI */ BusHandler = HalReferenceHandlerForBus(PCIBus, FdoExtension->BaseBus); FdoExtension->BusHandler = BusHandler; /* Fail if the HAL does not have a PCI Bus Handler for this bus */ if (!BusHandler) return STATUS_INVALID_DEVICE_REQUEST; } /* Appropriate interface was obtained */ return STATUS_SUCCESS; }
VOID NTAPI PciGetHotPlugParameters(IN PPCI_FDO_EXTENSION FdoExtension) { ACPI_EVAL_INPUT_BUFFER InputBuffer; PACPI_EVAL_OUTPUT_BUFFER OutputBuffer; ULONG Length; NTSTATUS Status; PAGED_CODE(); /* We should receive 4 parameters, per the HPP specification */ Length = sizeof(ACPI_EVAL_OUTPUT_BUFFER) + 4 * sizeof(ACPI_METHOD_ARGUMENT); /* Allocate the buffer to hold the parameters */ OutputBuffer = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG); if (!OutputBuffer) return; /* Initialize the output and input buffers. The method is _HPP */ RtlZeroMemory(OutputBuffer, Length); *(PULONG)InputBuffer.MethodName = 'PPH_'; InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; do { /* Send the IOCTL to the ACPI driver */ Status = PciSendIoctl(FdoExtension->PhysicalDeviceObject, IOCTL_ACPI_EVAL_METHOD, &InputBuffer, sizeof(InputBuffer), OutputBuffer, Length); if (!NT_SUCCESS(Status)) { /* The method failed, check if we can salvage data from parent */ if (!PCI_IS_ROOT_FDO(FdoExtension)) { /* Copy the root bus' hot plug parameters */ FdoExtension->HotPlugParameters = FdoExtension->ParentFdoExtension->HotPlugParameters; } /* Nothing more to do on this path */ break; } /* ACPI sent back some data. 4 parameters are expected in the output */ if (OutputBuffer->Count != 4) break; /* HotPlug PCI Support not yet implemented */ UNIMPLEMENTED_DBGBREAK(); } while (FALSE); /* Free the buffer and return */ ExFreePoolWithTag(OutputBuffer, 0); }
VOID NTAPI PciReadWriteConfigSpace(IN PPCI_FDO_EXTENSION DeviceExtension, IN PCI_SLOT_NUMBER Slot, IN PVOID Buffer, IN ULONG Offset, IN ULONG Length, IN BOOLEAN Read) { PPCI_BUS_INTERFACE_STANDARD PciInterface; PBUS_HANDLER BusHandler; PPCIBUSDATA BusData; PciReadWriteConfig HalFunction; /* Only the root FDO can access configuration space */ ASSERT(PCI_IS_ROOT_FDO(DeviceExtension->BusRootFdoExtension)); /* Get the ACPI-compliant PCI interface */ PciInterface = DeviceExtension->BusRootFdoExtension->PciBusInterface; if (PciInterface) { /* Currently this driver only supports the legacy HAL interface */ UNIMPLEMENTED; while (TRUE); } else { /* Make sure there's a registered HAL bus handler */ ASSERT(DeviceExtension->BusHandler); /* PCI Bus Number assignment is only valid on ACPI systems */ ASSERT(!PciAssignBusNumbers); /* Grab the HAL PCI Bus Handler data */ BusHandler = (PBUS_HANDLER)DeviceExtension->BusHandler; BusData = (PPCIBUSDATA)BusHandler->BusData; /* Choose the appropriate read or write function, and call it */ HalFunction = Read ? BusData->ReadConfig : BusData->WriteConfig; HalFunction(BusHandler, Slot, Buffer, Offset, Length); } }
VOID NTAPI ario_ApplyBrokenVideoHack(IN PPCI_FDO_EXTENSION FdoExtension) { PPCI_ARBITER_INSTANCE PciArbiter; //PARBITER_INSTANCE CommonInstance; //NTSTATUS Status; /* Only valid for root FDOs who are being applied the hack for the first time */ ASSERT(!FdoExtension->BrokenVideoHackApplied); ASSERT(PCI_IS_ROOT_FDO(FdoExtension)); /* Find the I/O arbiter */ PciArbiter = (PVOID)PciFindNextSecondaryExtension(FdoExtension-> SecondaryExtension.Next, PciArb_Io); ASSERT(PciArbiter); #if 0 // when arb exist /* Get the Arb instance */ CommonInstance = &PciArbiter->CommonInstance; /* Free the two lists, enabling full VGA access */ ArbFreeOrderingList(&CommonInstance->OrderingList); ArbFreeOrderingList(&CommonInstance->ReservedList); /* Build the ordering for broken video PCI access */ Status = ArbBuildAssignmentOrdering(CommonInstance, L"Pci", L"BrokenVideo", NULL); ASSERT(NT_SUCCESS(Status)); #else //Status = STATUS_SUCCESS; UNIMPLEMENTED; while (TRUE); #endif /* Now the hack has been applied */ FdoExtension->BrokenVideoHackApplied = TRUE; }
NTSTATUS NTAPI PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) { PPCI_INTERFACE CurrentInterface, *Interfaces; PPCI_PDO_EXTENSION PdoExtension; PPCI_ARBITER_INSTANCE ArbiterInterface; NTSTATUS Status; PCI_SIGNATURE ArbiterType; ASSERT_FDO(FdoExtension); /* Loop all the arbiters */ for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_BusNumber; ArbiterType++) { /* Check if this is the extension for the Root PCI Bus */ if (!PCI_IS_ROOT_FDO(FdoExtension)) { /* Get the PDO extension */ PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension; ASSERT_PDO(PdoExtension); /* Skip this bus if it does subtractive decode */ if (PdoExtension->Dependent.type1.SubtractiveDecode) { DPRINT1("PCI Not creating arbiters for subtractive bus %u\n", PdoExtension->Dependent.type1.SubtractiveDecode); continue; } } /* Query all the registered arbiter interfaces */ Interfaces = PciInterfaces; while (*Interfaces) { /* Find the one that matches the arbiter currently being setup */ CurrentInterface = *Interfaces; if (CurrentInterface->Signature == ArbiterType) break; Interfaces++; } /* Check if the required arbiter was not found in the list */ if (!*Interfaces) { /* Skip this arbiter and try the next one */ DPRINT1("PCI - FDO ext 0x%p no %s arbiter.\n", FdoExtension, PciArbiterNames[ArbiterType - PciArb_Io]); continue; } /* An arbiter was found, allocate an instance for it */ Status = STATUS_INSUFFICIENT_RESOURCES; ArbiterInterface = ExAllocatePoolWithTag(PagedPool, sizeof(PCI_ARBITER_INSTANCE), PCI_POOL_TAG); if (!ArbiterInterface) break; /* Setup the instance */ ArbiterInterface->BusFdoExtension = FdoExtension; ArbiterInterface->Interface = CurrentInterface; swprintf(ArbiterInterface->InstanceName, L"PCI %S (b=%02x)", PciArbiterNames[ArbiterType - PciArb_Io], FdoExtension->BaseBus); /* Call the interface initializer for it */ Status = CurrentInterface->Initializer(ArbiterInterface); if (!NT_SUCCESS(Status)) break; /* Link it with this FDO */ PcipLinkSecondaryExtension(&FdoExtension->SecondaryExtension, &FdoExtension->SecondaryExtLock, &ArbiterInterface->Header, ArbiterType, PciArbiterDestructor); /* This arbiter is now initialized, move to the next one */ DPRINT1("PCI - FDO ext 0x%p %S arbiter initialized (context 0x%p).\n", FdoExtension, L"ARBITER HEADER MISSING", //ArbiterInterface->CommonInstance.Name, ArbiterInterface); Status = STATUS_SUCCESS; } /* Return to caller */ return Status; }
NTSTATUS NTAPI PciInitializeArbiterRanges(IN PPCI_FDO_EXTENSION DeviceExtension, IN PCM_RESOURCE_LIST Resources) { PPCI_PDO_EXTENSION PdoExtension; //CM_RESOURCE_TYPE DesiredType; PVOID Instance; PCI_SIGNATURE ArbiterType; UNREFERENCED_PARAMETER(Resources); /* Arbiters should not already be initialized */ if (DeviceExtension->ArbitersInitialized) { /* Duplicated start request, fail initialization */ DPRINT1("PCI Warning hot start FDOx %p, resource ranges not checked.\n", DeviceExtension); return STATUS_INVALID_DEVICE_REQUEST; } /* Check for non-root FDO */ if (!PCI_IS_ROOT_FDO(DeviceExtension)) { /* Grab the PDO */ PdoExtension = (PPCI_PDO_EXTENSION)DeviceExtension->PhysicalDeviceObject->DeviceExtension; ASSERT_PDO(PdoExtension); /* Check if this is a subtractive bus */ if (PdoExtension->Dependent.type1.SubtractiveDecode) { /* There is nothing to do regarding arbitration of resources */ DPRINT1("PCI Skipping arbiter initialization for subtractive bridge FDOX %p\n", DeviceExtension); return STATUS_SUCCESS; } } /* Loop all arbiters */ for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++) { /* Pick correct resource type for each arbiter */ if (ArbiterType == PciArb_Io) { /* I/O Port */ //DesiredType = CmResourceTypePort; } else if (ArbiterType == PciArb_Memory) { /* Device RAM */ //DesiredType = CmResourceTypeMemory; } else { /* Ignore anything else */ continue; } /* Find an arbiter of this type */ Instance = PciFindNextSecondaryExtension(&DeviceExtension->SecondaryExtension, ArbiterType); if (Instance) { /* * Now we should initialize it, not yet implemented because Arb * library isn't yet implemented, not even the headers. */ UNIMPLEMENTED; //while (TRUE); } else { /* The arbiter was not found, this is an error! */ DPRINT1("PCI - FDO ext 0x%p %s arbiter (REQUIRED) is missing.\n", DeviceExtension, PciArbiterNames[ArbiterType - PciArb_Io]); } } /* Arbiters are now initialized */ DeviceExtension->ArbitersInitialized = TRUE; return STATUS_SUCCESS; }
NTSTATUS NTAPI PciQueryId(IN PPCI_PDO_EXTENSION DeviceExtension, IN BUS_QUERY_ID_TYPE QueryType, OUT PWCHAR *Buffer) { ULONG SubsysId; CHAR VendorString[22]; PPCI_PDO_EXTENSION PdoExtension; PPCI_FDO_EXTENSION ParentExtension; PWCHAR StringBuffer; ULONG i, Size; NTSTATUS Status; PANSI_STRING NextString; UNICODE_STRING DestinationString; PCI_ID_BUFFER IdBuffer; PAGED_CODE(); /* Assume failure */ Status = STATUS_SUCCESS; *Buffer = NULL; /* Start with the genric vendor string, which is the vendor ID + device ID */ sprintf(VendorString, "PCI\\VEN_%04X&DEV_%04X", DeviceExtension->VendorId, DeviceExtension->DeviceId); /* Initialize the PCI ID Buffer */ PciInitIdBuffer(&IdBuffer); /* Build the subsystem ID as shown in PCI ID Strings */ SubsysId = DeviceExtension->SubsystemVendorId | (DeviceExtension->SubsystemId << 16); /* Check what the caller is requesting */ switch (QueryType) { case BusQueryDeviceID: /* A single ID, the vendor string + the revision ID */ PciIdPrintf(&IdBuffer, "%s&SUBSYS_%08X&REV_%02X", VendorString, SubsysId, DeviceExtension->RevisionId); break; case BusQueryHardwareIDs: /* First the vendor string + the subsystem ID + the revision ID */ PciIdPrintf(&IdBuffer, "%s&SUBSYS_%08X&REV_%02X", VendorString, SubsysId, DeviceExtension->RevisionId); /* Next, without the revision */ PciIdPrintf(&IdBuffer, "%s&SUBSYS_%08X", VendorString, SubsysId); /* Next, the vendor string + the base class + sub class + progif */ PciIdPrintf(&IdBuffer, "%s&CC_%02X%02X%02X", VendorString, DeviceExtension->BaseClass, DeviceExtension->SubClass, DeviceExtension->ProgIf); /* Next, without the progif */ PciIdPrintf(&IdBuffer, "%s&CC_%02X%02X", VendorString, DeviceExtension->BaseClass, DeviceExtension->SubClass); /* And finally, a terminator */ PciIdPrintf(&IdBuffer, "\0"); break; case BusQueryCompatibleIDs: /* First, the vendor + revision ID only */ PciIdPrintf(&IdBuffer, "%s&REV_%02X", VendorString, DeviceExtension->RevisionId); /* Next, the vendor string alone */ PciIdPrintf(&IdBuffer, "%s", VendorString); /* Next, the vendor ID + the base class + the sub class + progif */ PciIdPrintf(&IdBuffer, "PCI\\VEN_%04X&CC_%02X%02X%02X", DeviceExtension->VendorId, DeviceExtension->BaseClass, DeviceExtension->SubClass, DeviceExtension->ProgIf); /* Now without the progif */ PciIdPrintf(&IdBuffer, "PCI\\VEN_%04X&CC_%02X%02X", DeviceExtension->VendorId, DeviceExtension->BaseClass, DeviceExtension->SubClass); /* And then just the vendor ID itself */ PciIdPrintf(&IdBuffer, "PCI\\VEN_%04X", DeviceExtension->VendorId); /* Then the base class + subclass + progif, without any vendor */ PciIdPrintf(&IdBuffer, "PCI\\CC_%02X%02X%02X", DeviceExtension->BaseClass, DeviceExtension->SubClass, DeviceExtension->ProgIf); /* Next, without the progif */ PciIdPrintf(&IdBuffer, "PCI\\CC_%02X%02X", DeviceExtension->BaseClass, DeviceExtension->SubClass); /* And finally, a terminator */ PciIdPrintf(&IdBuffer, "\0"); break; case BusQueryInstanceID: /* Start with a terminator */ PciIdPrintf(&IdBuffer, "\0"); /* And then encode the device and function number */ PciIdPrintfAppend(&IdBuffer, "%02X", (DeviceExtension->Slot.u.bits.DeviceNumber << 3) | DeviceExtension->Slot.u.bits.FunctionNumber); /* Loop every parent until the root */ ParentExtension = DeviceExtension->ParentFdoExtension; while (!PCI_IS_ROOT_FDO(ParentExtension)) { /* And encode the parent's device and function number as well */ PdoExtension = ParentExtension->PhysicalDeviceObject->DeviceExtension; PciIdPrintfAppend(&IdBuffer, "%02X", (PdoExtension->Slot.u.bits.DeviceNumber << 3) | PdoExtension->Slot.u.bits.FunctionNumber); } break; default: /* Unknown query type */ DPRINT1("PciQueryId expected ID type = %d\n", QueryType); return STATUS_NOT_SUPPORTED; } /* Something should've been generated if this has been reached */ ASSERT(IdBuffer.Count > 0); /* Allocate the final string buffer to hold the ID */ StringBuffer = ExAllocatePoolWithTag(PagedPool, IdBuffer.TotalLength, 'BicP'); if (!StringBuffer) return STATUS_INSUFFICIENT_RESOURCES; /* Build the UNICODE_STRING structure for it */ DPRINT1("PciQueryId(%d)\n", QueryType); DestinationString.Buffer = StringBuffer; DestinationString.MaximumLength = IdBuffer.TotalLength; /* Loop every ID in the buffer */ for (i = 0; i < IdBuffer.Count; i++) { /* Select the ANSI_STRING for the ID */ NextString = &IdBuffer.Strings[i]; DPRINT1(" <- \"%s\"\n", NextString->Buffer); /* Convert it to a UNICODE_STRING */ Status = RtlAnsiStringToUnicodeString(&DestinationString, NextString, FALSE); ASSERT(NT_SUCCESS(Status)); /* Add it into the final destination buffer */ Size = IdBuffer.StringSize[i]; DestinationString.MaximumLength -= Size; DestinationString.Buffer += (Size / sizeof(WCHAR)); } /* Return the buffer to the caller and return status (should be success) */ *Buffer = StringBuffer; return Status; }
NTSTATUS NTAPI PciQueryInterface(IN PPCI_FDO_EXTENSION DeviceExtension, IN CONST GUID* InterfaceType, IN ULONG Size, IN ULONG Version, IN PVOID InterfaceData, IN PINTERFACE Interface, IN BOOLEAN LastChance) { UNICODE_STRING GuidString; NTSTATUS Status; PPCI_INTERFACE *InterfaceList; PPCI_INTERFACE PciInterface; RtlStringFromGUID(InterfaceType, &GuidString); DPRINT1("PCI - PciQueryInterface TYPE = %wZ\n", &GuidString); RtlFreeUnicodeString(&GuidString); DPRINT1(" Size = %u, Version = %u, InterfaceData = %p, LastChance = %s\n", Size, Version, InterfaceData, LastChance ? "TRUE" : "FALSE"); /* Loop all the available interfaces */ for (InterfaceList = LastChance ? PciInterfacesLastResort : PciInterfaces; *InterfaceList; InterfaceList++) { /* Get the current interface */ PciInterface = *InterfaceList; /* For debugging, construct the GUID string */ RtlStringFromGUID(PciInterface->InterfaceType, &GuidString); /* Check if this is an FDO or PDO */ if (DeviceExtension->ExtensionType == PciFdoExtensionType) { /* Check if the interface is for FDOs */ if (!(PciInterface->Flags & PCI_INTERFACE_FDO)) { /* This interface is not for FDOs, skip it */ DPRINT1("PCI - PciQueryInterface: guid = %wZ only for FDOs\n", &GuidString); RtlFreeUnicodeString(&GuidString); continue; } /* Check if the interface is for root FDO only */ if ((PciInterface->Flags & PCI_INTERFACE_ROOT) && (!PCI_IS_ROOT_FDO(DeviceExtension))) { /* This FDO isn't the root, skip the interface */ DPRINT1("PCI - PciQueryInterface: guid = %wZ only for ROOT\n", &GuidString); RtlFreeUnicodeString(&GuidString); continue; } } else { /* This is a PDO, check if the interface is for PDOs too */ if (!(PciInterface->Flags & PCI_INTERFACE_PDO)) { /* It isn't, skip it */ DPRINT1("PCI - PciQueryInterface: guid = %wZ only for PDOs\n", &GuidString); RtlFreeUnicodeString(&GuidString); continue; } } /* Print the GUID for debugging, and then free the string */ DPRINT1("PCI - PciQueryInterface looking at guid = %wZ\n", &GuidString); RtlFreeUnicodeString(&GuidString); /* Check if the GUID, version, and size all match */ if ((IsEqualGUIDAligned(PciInterface->InterfaceType, InterfaceType)) && (Version >= PciInterface->MinVersion) && (Version <= PciInterface->MaxVersion) && (Size >= PciInterface->MinSize)) { /* Call the interface's constructor */ Status = PciInterface->Constructor(DeviceExtension, PciInterface, InterfaceData, Version, Size, Interface); if (!NT_SUCCESS(Status)) { /* This interface was not initialized correctly, skip it */ DPRINT1("PCI - PciQueryInterface - Contructor %p = %08lx\n", PciInterface->Constructor, Status); continue; } /* Reference the interface and return success, all is good */ Interface->InterfaceReference(Interface->Context); DPRINT1("PCI - PciQueryInterface returning SUCCESS\n"); return Status; } } /* An interface of this type, and for this device, could not be found */ DPRINT1("PCI - PciQueryInterface FAILED TO FIND INTERFACE\n"); return STATUS_NOT_SUPPORTED; }
NTSTATUS NTAPI PciQueryForPciBusInterface(IN PPCI_FDO_EXTENSION FdoExtension) { PDEVICE_OBJECT AttachedDevice; IO_STATUS_BLOCK IoStatusBlock; KEVENT Event; NTSTATUS Status; PIRP Irp; PIO_STACK_LOCATION IoStackLocation; PPCI_BUS_INTERFACE_STANDARD PciInterface; PAGED_CODE(); ASSERT(PCI_IS_ROOT_FDO(FdoExtension)); /* Allocate space for the inteface */ PciInterface = ExAllocatePoolWithTag(NonPagedPool, sizeof(PCI_BUS_INTERFACE_STANDARD), PCI_POOL_TAG); if (!PciInterface) return STATUS_INSUFFICIENT_RESOURCES; /* Get the device the PDO is attached to, should be the Root (ACPI) */ AttachedDevice = IoGetAttachedDeviceReference(FdoExtension->PhysicalDeviceObject); /* Build an IRP for this request */ KeInitializeEvent(&Event, SynchronizationEvent, FALSE); Irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP, AttachedDevice, NULL, 0, NULL, &Event, &IoStatusBlock); if (Irp) { /* Initialize the default PnP response */ Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; Irp->IoStatus.Information = 0; /* Make it a Query Interface IRP */ IoStackLocation = IoGetNextIrpStackLocation(Irp); ASSERT(IoStackLocation->MajorFunction == IRP_MJ_PNP); IoStackLocation->MinorFunction = IRP_MN_QUERY_INTERFACE; IoStackLocation->Parameters.QueryInterface.InterfaceType = &GUID_PCI_BUS_INTERFACE_STANDARD; IoStackLocation->Parameters.QueryInterface.Size = sizeof(GUID_PCI_BUS_INTERFACE_STANDARD); IoStackLocation->Parameters.QueryInterface.Version = PCI_BUS_INTERFACE_STANDARD_VERSION; IoStackLocation->Parameters.QueryInterface.Interface = (PINTERFACE)PciInterface; IoStackLocation->Parameters.QueryInterface.InterfaceSpecificData = NULL; /* Send it to the root PDO */ Status = IoCallDriver(AttachedDevice, Irp); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; } /* Check if an interface was returned */ if (!NT_SUCCESS(Status)) { /* No interface was returned by the root PDO */ FdoExtension->PciBusInterface = NULL; ExFreePoolWithTag(PciInterface, 0); } else { /* An interface was returned, save it */ FdoExtension->PciBusInterface = PciInterface; } /* Dereference the device object because we took a reference earlier */ ObfDereferenceObject(AttachedDevice); } else { /* Failure path, dereference the device object and set failure code */ if (AttachedDevice) ObfDereferenceObject(AttachedDevice); ExFreePoolWithTag(PciInterface, 0); Status = STATUS_INSUFFICIENT_RESOURCES; } /* Return status code to caller */ return Status; }