diff --git a/reactos/drivers/bus/pcix/arb/arb_comn.c b/reactos/drivers/bus/pcix/arb/arb_comn.c index 37591694584..4f89c95b684 100644 --- a/reactos/drivers/bus/pcix/arb/arb_comn.c +++ b/reactos/drivers/bus/pcix/arb/arb_comn.c @@ -14,6 +14,111 @@ /* GLOBALS ********************************************************************/ +PCHAR PciArbiterNames[] = +{ + "I/O Port", + "Memory", + "Interrupt", + "Bus Number" +}; + /* FUNCTIONS ******************************************************************/ +VOID +NTAPI +PciArbiterDestructor(IN PPCI_ARBITER_INSTANCE Arbiter) +{ + /* This function is not yet implemented */ + UNIMPLEMENTED; + while (TRUE); +} + +NTSTATUS +NTAPI +PciInitializeArbiters(IN PPCI_FDO_EXTENSION FdoExtension) +{ + PPCI_INTERFACE CurrentInterface, *Interfaces; + PPCI_ARBITER_INSTANCE ArbiterInterface; + NTSTATUS Status; + PCI_SIGNATURE ArbiterType; + ASSERT_FDO(FdoExtension); + + /* Loop all the arbiters */ + for (ArbiterType = PciArb_Io; ArbiterType <= PciArb_Memory; ArbiterType++) + { + /* Check if this is the extension for the Root PCI Bus */ + if (!PCI_IS_ROOT_FDO(FdoExtension)) + { +#if 0 // at next sync when PDO add + /* Get the PDO extension */ + PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension; + ASSERT_PDO(PdoExtension); + + /* Skip this bus if it does subtractive decode */ + if (PdoExtension->Substractive) + { + DPRINT1("PCI Not creating arbiters for subtractive bus %d\n", + PdoExtension->Substractive); + continue; + } +#endif + } + + /* 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%08x 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%08x %S arbiter initialized (context 0x%08x).\n", + FdoExtension, + "ARBITER HEADER MISSING", //ArbiterInterface->CommonInstance.Name, + ArbiterInterface); + Status = STATUS_SUCCESS; + } + + /* Return to caller */ + return Status; +} /* EOF */ diff --git a/reactos/drivers/bus/pcix/dispatch.c b/reactos/drivers/bus/pcix/dispatch.c index 4bba2d253b2..dd40f1063cc 100644 --- a/reactos/drivers/bus/pcix/dispatch.c +++ b/reactos/drivers/bus/pcix/dispatch.c @@ -27,4 +27,16 @@ PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject, return STATUS_SUCCESS; } +NTSTATUS +NTAPI +PciIrpNotSupported(IN PIRP Irp, + IN PIO_STACK_LOCATION IoStackLocation, + IN PPCI_FDO_EXTENSION DeviceExtension) +{ + /* Not supported */ + DPRINT1("WARNING: PCI received unsupported IRP!\n"); + DbgBreakPoint(); + return STATUS_NOT_SUPPORTED; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/fdo.c b/reactos/drivers/bus/pcix/fdo.c index b03dca7e591..6ba70d34fa4 100644 --- a/reactos/drivers/bus/pcix/fdo.c +++ b/reactos/drivers/bus/pcix/fdo.c @@ -14,17 +14,306 @@ /* GLOBALS ********************************************************************/ +SINGLE_LIST_ENTRY PciFdoExtensionListHead; +BOOLEAN PciBreakOnDefault; + +PCI_MN_DISPATCH_TABLE PciFdoDispatchPowerTable[] = +{ + {IRP_DISPATCH, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported} +}; + +PCI_MN_DISPATCH_TABLE PciFdoDispatchPnpTable[] = +{ + {IRP_UPWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DISPATCH, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DISPATCH, PciIrpNotSupported}, + {IRP_UPWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_UPWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported}, + {IRP_DOWNWARD, PciIrpNotSupported} +}; + +PCI_MJ_DISPATCH_TABLE PciFdoDispatchTable = +{ + IRP_MN_QUERY_LEGACY_BUS_INFORMATION, + PciFdoDispatchPnpTable, + IRP_MN_QUERY_POWER, + PciFdoDispatchPowerTable, + IRP_DOWNWARD, + PciIrpNotSupported, + IRP_DOWNWARD, + PciIrpNotSupported +}; + /* FUNCTIONS ******************************************************************/ +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; + while (TRUE); + } while (FALSE); + + /* Free the buffer and return */ + ExFreePoolWithTag(OutputBuffer, 0); +} + +VOID +NTAPI +PciInitializeFdoExtensionCommonFields(PPCI_FDO_EXTENSION FdoExtension, + IN PDEVICE_OBJECT DeviceObject, + IN PDEVICE_OBJECT PhysicalDeviceObject) +{ + /* Initialize the extension */ + RtlZeroMemory(FdoExtension, sizeof(PCI_FDO_EXTENSION)); + + /* Setup the common fields */ + FdoExtension->PhysicalDeviceObject = PhysicalDeviceObject; + FdoExtension->FunctionalDeviceObject = DeviceObject; + FdoExtension->ExtensionType = PciFdoExtensionType; + FdoExtension->PowerState.CurrentSystemState = PowerSystemWorking; + FdoExtension->PowerState.CurrentDeviceState = PowerDeviceD0; + FdoExtension->IrpDispatchTable = &PciFdoDispatchTable; + + /* Initialize the extension locks */ + KeInitializeEvent(&FdoExtension->SecondaryExtLock, SynchronizationEvent, TRUE); + KeInitializeEvent(&FdoExtension->ChildListLock, SynchronizationEvent, TRUE); + + /* Initialize the default state */ + PciInitializeState(FdoExtension); +} + NTSTATUS NTAPI PciAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { - /* This function is not yet implemented */ - UNIMPLEMENTED; - while (TRUE); - return STATUS_SUCCESS; + PCM_RESOURCE_LIST Descriptor; + PDEVICE_OBJECT AttachedTo; + PPCI_FDO_EXTENSION FdoExtension; + PPCI_FDO_EXTENSION ParentExtension; + PDEVICE_OBJECT DeviceObject; + UCHAR Buffer[sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(ULONG)]; + PKEY_VALUE_PARTIAL_INFORMATION ValueInfo = (PKEY_VALUE_PARTIAL_INFORMATION)Buffer; + NTSTATUS Status; + HANDLE KeyHandle; + UNICODE_STRING ValueName; + ULONG ResultLength; + PAGED_CODE(); + DPRINT1("PCI - AddDevice (a new bus). PDO: %p (Driver: %wZ)\n", + PhysicalDeviceObject, &PhysicalDeviceObject->DriverObject->DriverName); + + /* Zero out variables so failure path knows what to do */ + AttachedTo = NULL; + do + { + /* Check if there's already a device extension for this bus */ + ParentExtension = PciFindParentPciFdoExtension(PhysicalDeviceObject, + &PciGlobalLock); + if (ParentExtension) + { + /* More than one PCI bus, this is not expected yet */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Create the FDO for the bus */ + Status = IoCreateDevice(DriverObject, + sizeof(PCI_FDO_EXTENSION), + NULL, + FILE_DEVICE_BUS_EXTENDER, + 0, + 0, + &DeviceObject); + if (!NT_SUCCESS(Status)) break; + + /* Initialize the extension for the FDO */ + FdoExtension = DeviceObject->DeviceExtension; + PciInitializeFdoExtensionCommonFields(DeviceObject->DeviceExtension, + DeviceObject, + PhysicalDeviceObject); + + /* Attach to the root PDO */ + Status = STATUS_NO_SUCH_DEVICE; + AttachedTo = IoAttachDeviceToDeviceStack(DeviceObject, + PhysicalDeviceObject); + ASSERT(AttachedTo != NULL); + if (!AttachedTo) break; + FdoExtension->AttachedDeviceObject = AttachedTo; + if (ParentExtension) + { + /* More than one PCI bus, this is not expected yet */ + UNIMPLEMENTED; + while (TRUE); + } + else + { + /* Query the boot configuration */ + Status = PciGetDeviceProperty(PhysicalDeviceObject, + DevicePropertyBootConfiguration, + (PVOID*)&Descriptor); + if (!NT_SUCCESS(Status)) + { + /* No configuration has been set */ + Descriptor = NULL; + } + else + { + /* Root PDO in ReactOS does not assign boot resources */ + UNIMPLEMENTED; + while (TRUE); + } + + if (Descriptor) + { + /* Root PDO in ReactOS does not assign boot resources */ + UNIMPLEMENTED; + while (TRUE); + } + else + { + /* Default configuration isn't the normal path on Windows */ + if (PciBreakOnDefault) + { + /* If a second bus is found and there's still no data, crash */ + KeBugCheckEx(PCI_BUS_DRIVER_INTERNAL, + 0xDEAD0010u, + (ULONG_PTR)DeviceObject, + 0, + 0); + } + + /* Warn that a default configuration will be used, and set bus 0 */ + DPRINT1("PCI Will use default configuration.\n"); + PciBreakOnDefault = TRUE; + FdoExtension->BaseBus = 0; + } + + /* This is the root bus */ + FdoExtension->BusRootFdoExtension = FdoExtension; + } + + /* Get the HAL or ACPI Bus Handler Callbacks for Configuration Access */ + Status = PciGetConfigHandlers(FdoExtension); + if (!NT_SUCCESS(Status)) break; + + /* Initialize all the supported PCI arbiters */ + Status = PciInitializeArbiters(FdoExtension); + if (!NT_SUCCESS(Status)) break; + + /* This is a real FDO, insert it into the list */ + FdoExtension->Fake = FALSE; + PciInsertEntryAtTail(&PciFdoExtensionListHead, + FdoExtension, + &PciGlobalLock); + + /* Open the device registry key so that we can query the errata flags */ + IoOpenDeviceRegistryKey(DeviceObject, + PLUGPLAY_REGKEY_DEVICE, + KEY_ALL_ACCESS, + &KeyHandle), + + /* Open the value that contains errata flags for this bus instance */ + RtlInitUnicodeString(&ValueName, L"HackFlags"); + Status = ZwQueryValueKey(KeyHandle, + &ValueName, + KeyValuePartialInformation, + ValueInfo, + sizeof(Buffer), + &ResultLength); + ZwClose(KeyHandle); + if (NT_SUCCESS(Status)) + { + /* Make sure the data is of expected type and size */ + if ((ValueInfo->Type == REG_DWORD) && + (ValueInfo->DataLength == sizeof(ULONG))) + { + /* Read the flags for this bus */ + FdoExtension->BusHackFlags = *(PULONG)&ValueInfo->Data; + } + } + + /* Query ACPI for PCI HotPlug Support */ + PciGetHotPlugParameters(FdoExtension); + + /* The Bus FDO is now initialized */ + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + DPRINT1("PCI Root FDO Added: %p %p\n", DeviceObject, FdoExtension); + return STATUS_SUCCESS; + } while (FALSE); + + /* This is the failure path */ + ASSERT(!NT_SUCCESS(Status)); + if (AttachedTo) IoDetachDevice(AttachedTo); + if (DeviceObject) IoDeleteDevice(DeviceObject); + return Status; } /* EOF */ diff --git a/reactos/drivers/bus/pcix/intrface/intrface.c b/reactos/drivers/bus/pcix/intrface/intrface.c index e8d0dd5e91a..2b75f8d97d9 100644 --- a/reactos/drivers/bus/pcix/intrface/intrface.c +++ b/reactos/drivers/bus/pcix/intrface/intrface.c @@ -14,6 +14,11 @@ /* GLOBALS ********************************************************************/ +PPCI_INTERFACE PciInterfaces[] = +{ + NULL +}; + /* FUNCTIONS ******************************************************************/ /* EOF */ diff --git a/reactos/drivers/bus/pcix/pci.h b/reactos/drivers/bus/pcix/pci.h index 9ffde145f01..b8125d28575 100644 --- a/reactos/drivers/bus/pcix/pci.h +++ b/reactos/drivers/bus/pcix/pci.h @@ -17,12 +17,24 @@ #include "halfuncs.h" #include "rtlfuncs.h" #include "vffuncs.h" +#include "bugcodes.h" // // Tag used in all pool allocations (Pci Bus) // #define PCI_POOL_TAG 'BicP' +// +// Checks if the specified FDO is the FDO for the Root PCI Bus +// +#define PCI_IS_ROOT_FDO(x) ((x)->BusRootFdoExtension == x) + +// +// Assertions to make sure we are dealing with the right kind of extension +// +#define ASSERT_FDO(x) ASSERT((x)->ExtensionType == PciFdoExtensionType); +#define ASSERT_PDO(x) ASSERT((x)->ExtensionType == PciPdoExtensionType); + // // PCI Hack Entry Name Lengths // @@ -32,10 +44,62 @@ #define PCI_HACK_ENTRY_FULL_SIZE sizeof(L"VVVVddddssssIIIIRR") // 36 // -// PCI Hack Entry Information +// PCI Hack Entry Flags // #define PCI_HACK_HAS_REVISION_INFO 0x01 #define PCI_HACK_HAS_SUBSYSTEM_INFO 0x02 + +// +// Device Extension, Interface, Translator and Arbiter Signatures +// +typedef enum _PCI_SIGNATURE +{ + PciPdoExtensionType = '0Pci', + PciFdoExtensionType = '1Pci', + PciArb_Io = '2Pci', + PciArb_Memory = '3Pci', + PciArb_Interrupt = '4Pci', + PciArb_BusNumber = '5Pci', + PciTrans_Interrupt = '6Pci', + PciInterface_BusHandler = '7Pci', + PciInterface_IntRouteHandler = '8Pci', + PciInterface_PciCb = '9Pci', + PciInterface_LegacyDeviceDetection = ':Pci', + PciInterface_PmeHandler = ';Pci', + PciInterface_DevicePresent = '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; +} + +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; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/pci/state.c b/reactos/drivers/bus/pcix/pci/state.c index d2f3048bf9e..994000f2043 100644 --- a/reactos/drivers/bus/pcix/pci/state.c +++ b/reactos/drivers/bus/pcix/pci/state.c @@ -16,4 +16,13 @@ /* FUNCTIONS ******************************************************************/ +VOID +NTAPI +PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension) +{ + /* Set the initial state */ + DeviceExtension->DeviceState = PciNotStarted; + DeviceExtension->TentativeNextState = PciNotStarted; +} + /* EOF */ diff --git a/reactos/drivers/bus/pcix/utils.c b/reactos/drivers/bus/pcix/utils.c index 9460e0681a3..2e068bba93c 100644 --- a/reactos/drivers/bus/pcix/utils.c +++ b/reactos/drivers/bus/pcix/utils.c @@ -333,4 +333,226 @@ PciBuildDefaultExclusionLists(VOID) return Status; } +PPCI_FDO_EXTENSION +NTAPI +PciFindParentPciFdoExtension(IN PDEVICE_OBJECT DeviceObject, + IN PKEVENT Lock) +{ + PPCI_FDO_EXTENSION FoundExtension; + + /* Assume we'll find nothing */ + FoundExtension = NULL; + + /* Check if a lock was specified */ + if (Lock) + { + /* Wait for the lock to be released */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(Lock, Executive, KernelMode, FALSE, NULL); + } + + /* Now search for the extension */ + if (PciFdoExtensionListHead.Next) + { + /* This case should not be hit yet */ + UNIMPLEMENTED; + while (TRUE); + } + + /* Check if we had acquired a lock previously */ + if (Lock) + { + /* Release it */ + KeSetEvent(Lock, IO_NO_INCREMENT, FALSE); + KeLeaveCriticalRegion(); + } + + /* Return which extension was found, if any */ + return FoundExtension; +} + +VOID +NTAPI +PciInsertEntryAtTail(IN PSINGLE_LIST_ENTRY ListHead, + IN PPCI_FDO_EXTENSION DeviceExtension, + IN PKEVENT Lock) +{ + PSINGLE_LIST_ENTRY NextEntry; + PAGED_CODE(); + + /* Check if a lock was specified */ + if (Lock) + { + /* Wait for the lock to be released */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(Lock, Executive, KernelMode, FALSE, NULL); + } + + /* Loop the list until we get to the end, then insert this entry there */ + for (NextEntry = ListHead; NextEntry->Next; NextEntry = NextEntry->Next); + NextEntry->Next = &DeviceExtension->List; + + /* Check if we had acquired a lock previously */ + if (Lock) + { + /* Release it */ + KeSetEvent(Lock, IO_NO_INCREMENT, FALSE); + KeLeaveCriticalRegion(); + } +} + +VOID +NTAPI +PciInsertEntryAtHead(IN PSINGLE_LIST_ENTRY ListHead, + IN PSINGLE_LIST_ENTRY Entry, + IN PKEVENT Lock) +{ + PAGED_CODE(); + + /* Check if a lock was specified */ + if (Lock) + { + /* Wait for the lock to be released */ + KeEnterCriticalRegion(); + KeWaitForSingleObject(Lock, Executive, KernelMode, FALSE, NULL); + } + + /* Make the entry point to the current head and make the head point to it */ + Entry->Next = ListHead->Next; + ListHead->Next = Entry; + + /* Check if we had acquired a lock previously */ + if (Lock) + { + /* Release it */ + KeSetEvent(Lock, IO_NO_INCREMENT, FALSE); + KeLeaveCriticalRegion(); + } +} + +VOID +NTAPI +PcipLinkSecondaryExtension(IN PSINGLE_LIST_ENTRY List, + IN PVOID Lock, + IN PPCI_SECONDARY_EXTENSION SecondaryExtension, + IN PCI_SIGNATURE ExtensionType, + IN PVOID Destructor) +{ + PAGED_CODE(); + + /* Setup the extension data, and insert it into the primary's list */ + SecondaryExtension->ExtensionType = ExtensionType; + SecondaryExtension->Destructor = Destructor; + PciInsertEntryAtHead(List, &SecondaryExtension->List, Lock); +} + +NTSTATUS +NTAPI +PciGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, + IN DEVICE_REGISTRY_PROPERTY DeviceProperty, + OUT PVOID *OutputBuffer) +{ + NTSTATUS Status; + ULONG BufferLength, ResultLength; + PVOID Buffer; + do + { + /* Query the requested property size */ + Status = IoGetDeviceProperty(DeviceObject, + DeviceProperty, + 0, + NULL, + &BufferLength); + if (Status != STATUS_BUFFER_TOO_SMALL) + { + /* Call should've failed with buffer too small! */ + DPRINT1("PCI - Unexpected status from GetDeviceProperty, saw %08X, expected %08X.\n", + Status, + STATUS_BUFFER_TOO_SMALL); + *OutputBuffer = NULL; + ASSERTMSG(FALSE, "PCI Successfully did the impossible!"); + break; + } + + /* Allocate the required buffer */ + Buffer = ExAllocatePoolWithTag(PagedPool, BufferLength, 'BicP'); + if (!Buffer) + { + /* No memory, fail the request */ + DPRINT1("PCI - Failed to allocate DeviceProperty buffer (%d bytes).\n", BufferLength); + Status = STATUS_INSUFFICIENT_RESOURCES; + break; + } + + /* Do the actual property query call */ + Status = IoGetDeviceProperty(DeviceObject, + DeviceProperty, + BufferLength, + Buffer, + &ResultLength); + if (!NT_SUCCESS(Status)) break; + + /* Return the buffer to the caller */ + ASSERT(BufferLength == ResultLength); + *OutputBuffer = Buffer; + return STATUS_SUCCESS; + } while (FALSE); + + /* Failure path */ + return STATUS_UNSUCCESSFUL; +} + +NTSTATUS +NTAPI +PciSendIoctl(IN PDEVICE_OBJECT DeviceObject, + IN ULONG IoControlCode, + IN PVOID InputBuffer, + IN ULONG InputBufferLength, + IN PVOID OutputBuffer, + IN ULONG OutputBufferLength) +{ + PIRP Irp; + NTSTATUS Status; + KEVENT Event; + IO_STATUS_BLOCK IoStatusBlock; + PDEVICE_OBJECT AttachedDevice; + PAGED_CODE(); + + /* Initialize the pending IRP event */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + + /* Get a reference to the root PDO (ACPI) */ + AttachedDevice = IoGetAttachedDeviceReference(DeviceObject); + if (!AttachedDevice) return STATUS_INVALID_PARAMETER; + + /* Build the requested IOCTL IRP */ + Irp = IoBuildDeviceIoControlRequest(IoControlCode, + AttachedDevice, + InputBuffer, + InputBufferLength, + OutputBuffer, + OutputBufferLength, + 0, + &Event, + &IoStatusBlock); + if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; + + /* Send the IOCTL to the driver */ + Status = IoCallDriver(AttachedDevice, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for a response */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = Irp->IoStatus.Status; + } + + /* Take away the reference we took and return the result to the caller */ + ObDereferenceObject(AttachedDevice); + return Status; +} + /* EOF */