Implement Root Bus FDO AddDevice codes, get boot config, connect to HAL or ACPI confi...
authorevb <evb@svn.reactos.org>
Mon, 28 Jun 2010 17:30:35 +0000 (17:30 +0000)
committerevb <evb@svn.reactos.org>
Mon, 28 Jun 2010 17:30:35 +0000 (17:30 +0000)
PciGetHotPlugParameters work but no PCI HotPlug support on my machines, so cannot test ACPI data, that part stub now
Add PciFdoDispatchTable, PciFdoDispatchPnpTable, PciFdoDispatchPowerTable but all stub to PciIrpNotSupported however set correct IRP Dispatch Style for the IRPS
Arbiter support in PciInitializeARbiters done, but PciInterfaces array is NULL (stub) at moment
Add PCI_SIGNATURE, PCI_STATE, PCI_DISAPTCH_STYLE type, add PciInitializeState to begin the state support
Add structure for PCI_FDO_EXTENSION, PCI_SECONDARY_EXTENSION, PCI_INTERFACE, PCI_ARBITER_INSTANCE, PCI_DISPATCH_TABLE
PCI utility functions added: PciFindParentPciFdoExtension, PciInsertEntryAtTail, PciInsertEntryAtHead, PcipLinkSecondaryExtension, PciGetDeviceProperty, PciSendIoctl
Need sir_richard to add arbiter.h header to define ARBITER_INSTANCE for finish support
This 1000 more codes done now~

svn path=/trunk/; revision=47898

reactos/drivers/bus/pcix/arb/arb_comn.c
reactos/drivers/bus/pcix/dispatch.c
reactos/drivers/bus/pcix/fdo.c
reactos/drivers/bus/pcix/intrface/intrface.c
reactos/drivers/bus/pcix/pci.h
reactos/drivers/bus/pcix/pci/config.c
reactos/drivers/bus/pcix/pci/state.c
reactos/drivers/bus/pcix/utils.c

index 3759169..4f89c95 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
 
 /* GLOBALS ********************************************************************/
 
+PCHAR PciArbiterNames[] =
+{
+    "I/O Port",
+    "Memory",
+    "Interrupt",
+    "Bus Number"
+};
+
 /* FUNCTIONS ******************************************************************/
 
 /* 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 */
 /* EOF */
index 4bba2d2..dd40f10 100644 (file)
@@ -27,4 +27,16 @@ PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject,
     return STATUS_SUCCESS;
 }
 
     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 */
 /* EOF */
index b03dca7..6ba70d3 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
 
 /* 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 ******************************************************************/
 
 /* 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)
 {
 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 */
 }
 
 /* EOF */
index e8d0dd5..2b75f8d 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
 
 /* GLOBALS ********************************************************************/
 
+PPCI_INTERFACE PciInterfaces[] =
+{
+    NULL
+};
+
 /* FUNCTIONS ******************************************************************/
 
 /* EOF */
 /* FUNCTIONS ******************************************************************/
 
 /* EOF */
index 9ffde14..b8125d2 100644 (file)
 #include "halfuncs.h"
 #include "rtlfuncs.h"
 #include "vffuncs.h"
 #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'
 
 
 //
 // 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
 //
 //
 // PCI Hack Entry Name Lengths
 //
 #define PCI_HACK_ENTRY_FULL_SIZE            sizeof(L"VVVVddddssssIIIIRR")   // 36
 
 //
 #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
 //
 #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 = '<Pci',
+    PciInterface_NativeIde = '=Pci',
+    PciInterface_AgpTarget = '>Pci',
+    PciInterface_Location  = '?Pci'
+} PCI_SIGNATURE, *PPCI_SIGNATURE;
+
+//
+// Device Extension Logic States
+//
+typedef enum _PCI_STATE
+{
+    PciNotStarted,
+    PciStarted,
+    PciDeleted,
+    PciStopped,
+    PciSurpriseRemoved,
+    PciSynchronizedOperation,
+    PciMaxObjectState
+} PCI_STATE;
+
+//
+// IRP Dispatch Logic Style
+//
+typedef enum _PCI_DISPATCH_STYLE
+{
+    IRP_COMPLETE,
+    IRP_DOWNWARD,
+    IRP_UPWARD,
+    IRP_DISPATCH,
+} PCI_DISPATCH_STYLE;
+
+//
+// PCI Hack Entry Information
+//
 typedef struct _PCI_HACK_ENTRY
 {
     USHORT VendorID;
 typedef struct _PCI_HACK_ENTRY
 {
     USHORT VendorID;
@@ -47,6 +111,165 @@ typedef struct _PCI_HACK_ENTRY
     UCHAR Flags;
 } PCI_HACK_ENTRY, *PPCI_HACK_ENTRY;
 
     UCHAR Flags;
 } PCI_HACK_ENTRY, *PPCI_HACK_ENTRY;
 
+//
+// Power State Information for Device Extension
+//
+typedef struct _PCI_POWER_STATE
+{
+    SYSTEM_POWER_STATE CurrentSystemState;
+    DEVICE_POWER_STATE CurrentDeviceState;
+    SYSTEM_POWER_STATE SystemWakeLevel;
+    DEVICE_POWER_STATE DeviceWakeLevel;
+    DEVICE_POWER_STATE SystemStateMapping[7];
+    PIRP WaitWakeIrp;
+    PVOID SavedCancelRoutine;
+    LONG Paging;
+    LONG Hibernate;
+    LONG CrashDump;
+} PCI_POWER_STATE, *PPCI_POWER_STATE;
+
+//
+// Internal PCI Lock Structure
+//
+typedef struct _PCI_LOCK
+{
+    LONG Atom;
+    BOOLEAN OldIrql;
+} PCI_LOCK, *PPCI_LOCK;
+
+//
+// Device Extension for a Bus FDO
+//
+typedef struct _PCI_FDO_EXTENSION
+{
+    SINGLE_LIST_ENTRY List;
+    ULONG ExtensionType;
+    struct _PCI_MJ_DISPATCH_TABLE *IrpDispatchTable;
+    BOOLEAN DeviceState;
+    BOOLEAN TentativeNextState;
+    KEVENT SecondaryExtLock;
+    PDEVICE_OBJECT PhysicalDeviceObject;
+    PDEVICE_OBJECT FunctionalDeviceObject;
+    PDEVICE_OBJECT AttachedDeviceObject;
+    KEVENT ChildListLock;
+    struct _PCI_PDO_EXTENSION *ChildPdoList;
+    struct _PCI_FDO_EXTENSION *BusRootFdoExtension;
+    struct _PCI_FDO_EXTENSION *ParentFdoExtension;
+    struct _PCI_PDO_EXTENSION *ChildBridgePdoList;
+    PPCI_BUS_INTERFACE_STANDARD PciBusInterface;
+    BOOLEAN MaxSubordinateBus;
+    BUS_HANDLER *BusHandler;
+    BOOLEAN BaseBus;
+    BOOLEAN Fake;
+    BOOLEAN ChildDelete;
+    BOOLEAN Scanned;
+    BOOLEAN ArbitersInitialized;
+    BOOLEAN BrokenVideoHackApplied;
+    BOOLEAN Hibernated;
+    PCI_POWER_STATE PowerState;
+    SINGLE_LIST_ENTRY SecondaryExtension;
+    LONG ChildWaitWakeCount;
+    PPCI_COMMON_CONFIG PreservedConfig;
+    PCI_LOCK Lock;
+    struct
+    {
+        BOOLEAN Acquired;
+        BOOLEAN CacheLineSize;
+        BOOLEAN LatencyTimer;
+        BOOLEAN EnablePERR;
+        BOOLEAN EnableSERR;
+    } HotPlugParameters;
+    LONG BusHackFlags;
+} PCI_FDO_EXTENSION, *PPCI_FDO_EXTENSION;
+
+//
+// IRP Dispatch Function Type
+//
+typedef NTSTATUS (NTAPI *PCI_DISPATCH_FUNCTION)(
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IoStackLocation,
+    IN PPCI_FDO_EXTENSION DeviceExtension
+);
+
+//
+// IRP Dispatch Minor Table
+//
+typedef struct _PCI_MN_DISPATCH_TABLE
+{
+    PCI_DISPATCH_STYLE DispatchStyle;
+    PCI_DISPATCH_FUNCTION DispatchFunction;
+} PCI_MN_DISPATCH_TABLE, *PPCI_MN_DISPATCH_TABLE;
+
+//
+// IRP Dispatch Major Table
+//
+typedef struct _PCI_MJ_DISPATCH_TABLE
+{
+    ULONG PnpIrpMaximumMinorFunction;
+    PPCI_MN_DISPATCH_TABLE PnpIrpDispatchTable;
+    ULONG PowerIrpMaximumMinorFunction;
+    PPCI_MN_DISPATCH_TABLE PowerIrpDispatchTable;
+    PCI_DISPATCH_STYLE SystemControlIrpDispatchStyle;
+    PCI_DISPATCH_FUNCTION SystemControlIrpDispatchFunction;
+    PCI_DISPATCH_STYLE OtherIrpDispatchStyle;
+    PCI_DISPATCH_FUNCTION OtherIrpDispatchFunction;
+} PCI_MJ_DISPATCH_TABLE, *PPCI_MJ_DISPATCH_TABLE;
+
+//
+// Generic PCI Interface Constructor and Initializer
+//
+struct _PCI_INTERFACE;
+typedef NTSTATUS (NTAPI *PCI_INTERFACE_CONSTRUCTOR)(
+    IN PPCI_FDO_EXTENSION DeviceExtension,
+    IN PVOID Instance,
+    IN PVOID InterfaceData,
+    IN USHORT Version,
+    IN USHORT Size,
+    IN PINTERFACE Interface
+);
+
+typedef NTSTATUS (NTAPI *PCI_INTERFACE_INITIALIZER)(
+    IN PVOID Instance
+);
+
+//
+// Generic PCI Interface (Interface, Translator, Arbiter)
+//
+typedef struct _PCI_INTERFACE
+{
+    LPGUID InterfaceType;
+    USHORT MinSize;
+    USHORT MinVersion;
+    USHORT MaxVersion;
+    USHORT Flags;
+    LONG ReferenceCount;
+    PCI_SIGNATURE Signature;
+    PCI_INTERFACE_CONSTRUCTOR Constructor;
+    PCI_INTERFACE_INITIALIZER Initializer;
+} PCI_INTERFACE, *PPCI_INTERFACE;
+
+//
+// Generic Secondary Extension Instance Header (Interface, Translator, Arbiter)
+//
+typedef struct PCI_SECONDARY_EXTENSION
+{
+    SINGLE_LIST_ENTRY List;
+    PCI_SIGNATURE ExtensionType;
+    PVOID Destructor;
+} PCI_SECONDARY_EXTENSION, *PPCI_SECONDARY_EXTENSION;
+
+//
+// PCI Arbiter Instance
+//
+typedef struct PCI_ARBITER_INSTANCE
+{
+    PCI_SECONDARY_EXTENSION Header;
+    PPCI_INTERFACE Interface;
+    PPCI_FDO_EXTENSION BusFdoExtension;
+    WCHAR InstanceName[24];
+    //ARBITER_INSTANCE CommonInstance; FIXME: Need Arbiter Headers
+} PCI_ARBITER_INSTANCE, *PPCI_ARBITER_INSTANCE;
+
 //
 // IRP Dispatch Routines
 //
 //
 // IRP Dispatch Routines
 //
@@ -57,6 +280,14 @@ PciDispatchIrp(
     IN PIRP Irp
 );
 
     IN PIRP Irp
 );
 
+NTSTATUS
+NTAPI
+PciIrpNotSupported(
+    IN PIRP Irp,
+    IN PIO_STACK_LOCATION IoStackLocation,
+    IN PPCI_FDO_EXTENSION DeviceExtension
+);
+
 //
 // Bus FDO Routines
 //
 //
 // Bus FDO Routines
 //
@@ -136,4 +367,82 @@ PciGetRegistryValue(
     OUT PULONG OutputLength
 );
 
     OUT PULONG OutputLength
 );
 
+PPCI_FDO_EXTENSION
+NTAPI
+PciFindParentPciFdoExtension(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PKEVENT Lock
+);
+
+VOID
+NTAPI
+PciInsertEntryAtTail(
+    IN PSINGLE_LIST_ENTRY ListHead,
+    IN PPCI_FDO_EXTENSION DeviceExtension,
+    IN PKEVENT Lock
+);
+
+NTSTATUS
+NTAPI
+PciGetDeviceProperty(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN DEVICE_REGISTRY_PROPERTY DeviceProperty,
+    OUT PVOID *OutputBuffer
+);
+
+NTSTATUS
+NTAPI
+PciSendIoctl(
+    IN PDEVICE_OBJECT DeviceObject,
+    IN ULONG IoControlCode,
+    IN PVOID InputBuffer,
+    IN ULONG InputBufferLength,
+    IN PVOID OutputBuffer,
+    IN ULONG OutputBufferLength
+);
+
+VOID
+NTAPI
+PcipLinkSecondaryExtension(
+    IN PSINGLE_LIST_ENTRY List,
+    IN PVOID Lock,
+    IN PPCI_SECONDARY_EXTENSION SecondaryExtension,
+    IN PCI_SIGNATURE ExtensionType,
+    IN PVOID Destructor
+);
+
+//
+// Configuration Routines
+//
+NTSTATUS
+NTAPI
+PciGetConfigHandlers(
+    IN PPCI_FDO_EXTENSION FdoExtension
+);
+
+//
+// State Machine Logic Transition Routines
+//
+VOID
+NTAPI
+PciInitializeState(
+    IN PPCI_FDO_EXTENSION DeviceExtension
+);
+
+//
+// Arbiter Support
+//
+NTSTATUS
+NTAPI
+PciInitializeArbiters(
+    IN PPCI_FDO_EXTENSION FdoExtension
+);
+
+//
+// External Resources
+//
+extern SINGLE_LIST_ENTRY PciFdoExtensionListHead;
+extern KEVENT PciGlobalLock;
+extern PPCI_INTERFACE PciInterfaces[];
+
 /* EOF */
 /* EOF */
index 9bdbb0f..f48c187 100644 (file)
 
 /* GLOBALS ********************************************************************/
 
 
 /* GLOBALS ********************************************************************/
 
+BOOLEAN PciAssignBusNumbers;
+
 /* FUNCTIONS ******************************************************************/
 
 /* FUNCTIONS ******************************************************************/
 
+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;
+}
+
+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 */
 /* EOF */
index d2f3048..994000f 100644 (file)
 
 /* FUNCTIONS ******************************************************************/
 
 
 /* FUNCTIONS ******************************************************************/
 
+VOID
+NTAPI
+PciInitializeState(IN PPCI_FDO_EXTENSION DeviceExtension)
+{
+    /* Set the initial state */
+    DeviceExtension->DeviceState = PciNotStarted;
+    DeviceExtension->TentativeNextState = PciNotStarted;
+}
+
 /* EOF */
 /* EOF */
index 9460e06..2e068bb 100644 (file)
@@ -333,4 +333,226 @@ PciBuildDefaultExclusionLists(VOID)
     return Status;
 }
 
     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 */
 /* EOF */