[USB-BRINGUP-TRUNK]
[reactos.git] / reactos / drivers / bus / pcix / enum.c
diff --git a/reactos/drivers/bus/pcix/enum.c b/reactos/drivers/bus/pcix/enum.c
deleted file mode 100644 (file)
index 5fb2070..0000000
+++ /dev/null
@@ -1,2262 +0,0 @@
-/*
- * PROJECT:         ReactOS PCI Bus Driver
- * LICENSE:         BSD - See COPYING.ARM in the top level directory
- * FILE:            drivers/bus/pci/enum.c
- * PURPOSE:         PCI Bus/Device Enumeration
- * PROGRAMMERS:     ReactOS Portable Systems Group
- */
-
-/* INCLUDES *******************************************************************/
-
-#include <pci.h>
-#define NDEBUG
-#include <debug.h>
-
-/* GLOBALS ********************************************************************/
-
-PIO_RESOURCE_REQUIREMENTS_LIST PciZeroIoResourceRequirements;
-
-PCI_CONFIGURATOR PciConfigurators[] =
-{
-    {
-        Device_MassageHeaderForLimitsDetermination,
-        Device_RestoreCurrent,
-        Device_SaveLimits,
-        Device_SaveCurrentSettings,
-        Device_ChangeResourceSettings,
-        Device_GetAdditionalResourceDescriptors,
-        Device_ResetDevice
-    },
-    {
-        PPBridge_MassageHeaderForLimitsDetermination,
-        PPBridge_RestoreCurrent,
-        PPBridge_SaveLimits,
-        PPBridge_SaveCurrentSettings,
-        PPBridge_ChangeResourceSettings,
-        PPBridge_GetAdditionalResourceDescriptors,
-        PPBridge_ResetDevice
-    },
-    {
-        Cardbus_MassageHeaderForLimitsDetermination,
-        Cardbus_RestoreCurrent,
-        Cardbus_SaveLimits,
-        Cardbus_SaveCurrentSettings,
-        Cardbus_ChangeResourceSettings,
-        Cardbus_GetAdditionalResourceDescriptors,
-        Cardbus_ResetDevice
-    }
-};
-
-/* FUNCTIONS ******************************************************************/
-
-BOOLEAN
-NTAPI
-PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
-                             IN PCM_RESOURCE_LIST ResourceList)
-{
-    PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial, InterruptResource;
-    PCM_PARTIAL_RESOURCE_DESCRIPTOR BaseResource, CurrentDescriptor;
-    PCM_PARTIAL_RESOURCE_DESCRIPTOR PreviousDescriptor;
-    CM_PARTIAL_RESOURCE_DESCRIPTOR ResourceArray[7];
-    PCM_FULL_RESOURCE_DESCRIPTOR FullList;
-    BOOLEAN DrainPartial, RangeChange;
-    ULONG i, j;
-    PPCI_FUNCTION_RESOURCES PciResources;
-    PAGED_CODE();
-
-    /* Make sure we have either no resources, or at least one */
-    ASSERT((ResourceList == NULL) || (ResourceList->Count == 1));
-
-    /* Initialize no partial, interrupt descriptor, or range change */
-    Partial = NULL;
-    InterruptResource = NULL;
-    RangeChange = FALSE;
-
-    /* Check if there's not actually any resources */
-    if (!(ResourceList) || !(ResourceList->Count))
-    {
-        /* Then just return the hardware update state */
-        return PdoExtension->UpdateHardware;
-    }
-
-    /* Print the new specified resource list */
-    PciDebugPrintCmResList(ResourceList);
-
-    /* Clear the temporary resource array */
-    for (i = 0; i < 7; i++) ResourceArray[i].Type = CmResourceTypeNull;
-
-    /* Loop the full resource descriptor */
-    FullList = ResourceList->List;
-    for (i = 0; i < ResourceList->Count; i++)
-    {
-        /* Initialize loop variables */
-        DrainPartial = FALSE;
-        BaseResource = NULL;
-
-        /* Loop the partial descriptors */
-        Partial = FullList->PartialResourceList.PartialDescriptors;
-        for (j = 0; j < FullList->PartialResourceList.Count; j++)
-        {
-            /* Check if we were supposed to drain a partial due to device data */
-            if (DrainPartial)
-            {
-                /* Draining complete, move on to the next descriptor then */
-                DrainPartial--;
-                continue;
-            }
-
-            /* Check what kind of descriptor this was */
-            switch (Partial->Type)
-            {
-                /* Base BAR resources */
-                case CmResourceTypePort:
-                case CmResourceTypeMemory:
-
-                    /* Set it as the base */
-                    ASSERT(BaseResource == NULL);
-                    BaseResource = Partial;
-                    break;
-
-                /* Interrupt resource */
-                case CmResourceTypeInterrupt:
-
-                    /* Make sure it's a compatible (and the only) PCI interrupt */
-                    ASSERT(InterruptResource == NULL);
-                    ASSERT(Partial->u.Interrupt.Level == Partial->u.Interrupt.Vector);
-                    InterruptResource = Partial;
-
-                    /* Only 255 interrupts on x86/x64 hardware */
-                    if (Partial->u.Interrupt.Level < 256)
-                    {
-                        /* Use the passed interrupt line */
-                        PdoExtension->AdjustedInterruptLine = Partial->u.Interrupt.Level;
-                    }
-                    else
-                    {
-                        /* Invalid vector, so ignore it */
-                        PdoExtension->AdjustedInterruptLine = 0;
-                    }
-
-                    break;
-
-                /* Check for specific device data */
-                case CmResourceTypeDevicePrivate:
-
-                    /* Check what kind of data this was */
-                    switch (Partial->u.DevicePrivate.Data[0])
-                    {
-                        /* Not used in the driver yet */
-                        case 1:
-                            UNIMPLEMENTED;
-                            while (TRUE);
-                            break;
-
-                        /* Not used in the driver yet */
-                        case 2:
-                            UNIMPLEMENTED;
-                            while (TRUE);
-                            break;
-
-                        /* A drain request */
-                        case 3:
-                            /* Shouldn't be a base resource, this is a drain */
-                            ASSERT(BaseResource == NULL);
-                            DrainPartial = Partial->u.DevicePrivate.Data[1];
-                            ASSERT(DrainPartial == TRUE);
-                            break;
-                    }
-                    break;
-            }
-
-            /* Move to the next descriptor */
-            Partial = PciNextPartialDescriptor(Partial);
-        }
-
-        /* We should be starting a new list now */
-        ASSERT(BaseResource == NULL);
-        FullList = (PVOID)Partial;
-    }
-
-    /* Check the current assigned PCI resources */
-    PciResources = PdoExtension->Resources;
-    if (!PciResources) return FALSE;
-
-    //if... // MISSING CODE
-    UNIMPLEMENTED;
-    DPRINT1("Missing sanity checking code!\n");
-
-    /* Loop all the PCI function resources */
-    for (i = 0; i < 7; i++)
-    {
-        /* Get the current function resource descriptor, and the new one */
-        CurrentDescriptor = &PciResources->Current[i];
-        Partial = &ResourceArray[i];
-
-        /* Previous is current during the first loop iteration */
-        PreviousDescriptor = &PciResources->Current[(i == 0) ? (0) : (i - 1)];
-
-        /* Check if this new descriptor is different than the old one */
-        if (((Partial->Type != CurrentDescriptor->Type) ||
-             (Partial->Type != CmResourceTypeNull)) &&
-            ((Partial->u.Generic.Start.QuadPart !=
-              CurrentDescriptor->u.Generic.Start.QuadPart) ||
-             (Partial->u.Generic.Length != CurrentDescriptor->u.Generic.Length)))
-        {
-            /* Record a change */
-            RangeChange = TRUE;
-
-            /* Was there a range before? */
-            if (CurrentDescriptor->Type != CmResourceTypeNull)
-            {
-                /* Print it */
-                DbgPrint("      Old range-\n");
-                PciDebugPrintPartialResource(CurrentDescriptor);
-            }
-            else
-            {
-                /* There was no range */
-                DbgPrint("      Previously unset range\n");
-            }
-
-            /* Print new one */
-            DbgPrint("      changed to\n");
-            PciDebugPrintPartialResource(Partial);
-
-            /* Update to new range */
-            CurrentDescriptor->Type = Partial->Type;
-            PreviousDescriptor->u.Generic.Start = Partial->u.Generic.Start;
-            PreviousDescriptor->u.Generic.Length = Partial->u.Generic.Length;
-            CurrentDescriptor = PreviousDescriptor;
-        }
-    }
-
-    /* Either the hardware was updated, or a resource range changed */
-    return ((RangeChange) || (PdoExtension->UpdateHardware));
-}
-
-VOID
-NTAPI
-PcipUpdateHardware(IN PVOID Context,
-                   IN PVOID Context2)
-{
-    PPCI_PDO_EXTENSION PdoExtension = Context;
-    PPCI_COMMON_HEADER PciData = Context2;
-
-    /* Check if we're allowed to disable decodes */
-    PciData->Command = PdoExtension->CommandEnables;
-    if (!(PdoExtension->HackFlags & PCI_HACK_PRESERVE_COMMAND))
-    {
-        /* Disable all decodes */
-        PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
-                              PCI_ENABLE_MEMORY_SPACE |
-                              PCI_ENABLE_BUS_MASTER |
-                              PCI_ENABLE_WRITE_AND_INVALIDATE);
-    }
-
-    /* Update the device configuration */
-    PciData->Status = 0;
-    PciWriteDeviceConfig(PdoExtension, PciData, 0, PCI_COMMON_HDR_LENGTH);
-
-    /* Turn decodes back on */
-    PciDecodeEnable(PdoExtension, TRUE, &PdoExtension->CommandEnables);
-}
-
-VOID
-NTAPI
-PciUpdateHardware(IN PPCI_PDO_EXTENSION PdoExtension,
-                  IN PPCI_COMMON_HEADER PciData)
-{
-    PCI_IPI_CONTEXT Context;
-
-    /* Check for critical devices and PCI Debugging devices */
-    if ((PdoExtension->HackFlags & PCI_HACK_CRITICAL_DEVICE) ||
-        (PdoExtension->OnDebugPath))
-    {
-        /* Build the context and send an IPI */
-        Context.RunCount = 1;
-        Context.Barrier = 1;
-        Context.Context = PciData;
-        Context.Function = PcipUpdateHardware;
-        Context.DeviceExtension = PdoExtension;
-        KeIpiGenericCall(PciExecuteCriticalSystemRoutine, (ULONG_PTR)&Context);
-    }
-    else
-    {
-        /* Just to the update inline */
-        PcipUpdateHardware(PdoExtension, PciData);
-    }
-}
-
-PIO_RESOURCE_REQUIREMENTS_LIST
-NTAPI
-PciAllocateIoRequirementsList(IN ULONG Count,
-                              IN ULONG BusNumber,
-                              IN ULONG SlotNumber)
-{
-    SIZE_T Size;
-    PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
-
-    /* Calculate the final size of the list, including each descriptor */
-    Size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
-    if (Count > 1) Size = sizeof(IO_RESOURCE_DESCRIPTOR) * (Count - 1) +
-                          sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
-
-    /* Allocate the list */
-    RequirementsList = ExAllocatePoolWithTag(PagedPool, Size, 'BicP');
-    if (!RequirementsList) return NULL;
-
-    /* Initialize it */
-    RtlZeroMemory(RequirementsList, Size);
-    RequirementsList->AlternativeLists = 1;
-    RequirementsList->BusNumber = BusNumber;
-    RequirementsList->SlotNumber = SlotNumber;
-    RequirementsList->InterfaceType = PCIBus;
-    RequirementsList->ListSize = Size;
-    RequirementsList->List[0].Count = Count;
-    RequirementsList->List[0].Version = 1;
-    RequirementsList->List[0].Revision = 1;
-
-    /* Return it */
-    return RequirementsList;
-}
-
-PCM_RESOURCE_LIST
-NTAPI
-PciAllocateCmResourceList(IN ULONG Count,
-                          IN ULONG BusNumber)
-{
-    SIZE_T Size;
-    PCM_RESOURCE_LIST ResourceList;
-
-    /* Calculate the final size of the list, including each descriptor */
-    Size = sizeof(CM_RESOURCE_LIST);
-    if (Count > 1) Size = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (Count - 1) +
-                          sizeof(CM_RESOURCE_LIST);
-
-    /* Allocate the list */
-    ResourceList = ExAllocatePoolWithTag(PagedPool, Size, 'BicP');
-    if (!ResourceList) return NULL;
-
-    /* Initialize it */
-    RtlZeroMemory(ResourceList, Size);
-    ResourceList->Count = 1;
-    ResourceList->List[0].BusNumber = BusNumber;
-    ResourceList->List[0].InterfaceType = PCIBus;
-    ResourceList->List[0].PartialResourceList.Version = 1;
-    ResourceList->List[0].PartialResourceList.Revision = 1;
-    ResourceList->List[0].PartialResourceList.Count = Count;
-
-    /* Return it */
-    return ResourceList;
-}
-
-NTSTATUS
-NTAPI
-PciQueryResources(IN PPCI_PDO_EXTENSION PdoExtension,
-                  OUT PCM_RESOURCE_LIST *Buffer)
-{
-    PPCI_FUNCTION_RESOURCES PciResources;
-    BOOLEAN HaveVga, HaveMemSpace, HaveIoSpace;
-    USHORT BridgeControl, PciCommand;
-    ULONG Count, i;
-    PCM_PARTIAL_RESOURCE_DESCRIPTOR Partial, Resource, LastResource;
-    PCM_RESOURCE_LIST ResourceList;
-    UCHAR InterruptLine;
-    PAGED_CODE();
-
-    /* Assume failure */
-    Count = 0;
-    HaveVga = FALSE;
-    *Buffer = NULL;
-
-    /* Make sure there's some resources to query */
-    PciResources = PdoExtension->Resources;
-    if (!PciResources) return STATUS_SUCCESS;
-
-    /* Read the decodes */
-    PciReadDeviceConfig(PdoExtension,
-                        &PciCommand,
-                        FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                        sizeof(USHORT));
-
-    /* Check which ones are turned on */
-    HaveIoSpace = PciCommand & PCI_ENABLE_IO_SPACE;
-    HaveMemSpace = PciCommand & PCI_ENABLE_MEMORY_SPACE;
-
-    /* Loop maximum possible descriptors */
-    for (i = 0; i < 7; i++)
-    {
-        /* Check if the decode for this descriptor is actually turned on */
-        Partial = &PciResources->Current[i];
-        if (((HaveMemSpace) && (Partial->Type == CmResourceTypeMemory)) ||
-            ((HaveIoSpace) && (Partial->Type == CmResourceTypePort)))
-        {
-            /* One more fully active descriptor */
-            Count++;
-        }
-    }
-
-    /* If there's an interrupt pin associated, check at least one decode is on */
-    if ((PdoExtension->InterruptPin) && ((HaveMemSpace) || (HaveIoSpace)))
-    {
-        /* Read the interrupt line for the pin, add a descriptor if it's valid */
-        InterruptLine = PdoExtension->AdjustedInterruptLine;
-        if ((InterruptLine) && (InterruptLine != -1)) Count++;
-    }
-
-    /* Check for PCI bridge */
-    if (PdoExtension->HeaderType == PCI_BRIDGE_TYPE)
-    {
-        /* Read bridge settings, check if VGA is present */
-        PciReadDeviceConfig(PdoExtension,
-                            &BridgeControl,
-                            FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BridgeControl),
-                            sizeof(USHORT));
-        if (BridgeControl & PCI_ENABLE_BRIDGE_VGA)
-        {
-            /* Remember for later */
-            HaveVga = TRUE;
-
-            /* One memory descriptor for 0xA0000, plus the two I/O port ranges */
-            if (HaveMemSpace) Count++;
-            if (HaveIoSpace) Count += 2;
-        }
-    }
-
-    /* If there's no descriptors in use, there's no resources, so return */
-    if (!Count) return STATUS_SUCCESS;
-
-    /* Allocate a resource list to hold the resources */
-    ResourceList = PciAllocateCmResourceList(Count,
-                                             PdoExtension->ParentFdoExtension->BaseBus);
-    if (!ResourceList) return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* This is where the descriptors will be copied into */
-    Resource = ResourceList->List[0].PartialResourceList.PartialDescriptors;
-    LastResource = Resource + Count + 1;
-
-    /* Loop maximum possible descriptors */
-    for (i = 0; i < 7; i++)
-    {
-        /* Check if the decode for this descriptor is actually turned on */
-        Partial = &PciResources->Current[i];
-        if (((HaveMemSpace) && (Partial->Type == CmResourceTypeMemory)) ||
-            ((HaveIoSpace) && (Partial->Type == CmResourceTypePort)))
-        {
-            /* Copy the descriptor into the resource list */
-            *Resource++ = *Partial;
-        }
-    }
-
-    /* Check if earlier the code detected this was a PCI bridge with VGA on it */
-    if (HaveVga)
-    {
-        /* Are the memory decodes enabled? */
-        if (HaveMemSpace)
-        {
-            /* Build a memory descriptor for a 128KB framebuffer at 0xA0000 */
-            Resource->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
-            Resource->u.Generic.Start.HighPart = 0;
-            Resource->Type = CmResourceTypeMemory;
-            Resource->u.Generic.Start.LowPart = 0xA0000;
-            Resource->u.Generic.Length = 0x20000;
-            Resource++;
-        }
-
-        /* Are the I/O decodes enabled? */
-        if (HaveIoSpace)
-        {
-            /* Build an I/O descriptor for the graphic ports at 0x3B0 */
-            Resource->Type = CmResourceTypePort;
-            Resource->Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | CM_RESOURCE_PORT_10_BIT_DECODE;
-            Resource->u.Port.Start.QuadPart = 0x3B0u;
-            Resource->u.Port.Length = 0xC;
-            Resource++;
-
-            /* Build an I/O descriptor for the graphic ports at 0x3C0 */
-            Resource->Type = CmResourceTypePort;
-            Resource->Flags = CM_RESOURCE_PORT_POSITIVE_DECODE | CM_RESOURCE_PORT_10_BIT_DECODE;
-            Resource->u.Port.Start.QuadPart = 0x3C0u;
-            Resource->u.Port.Length = 0x20;
-            Resource++;
-        }
-    }
-
-    /* If there's an interrupt pin associated, check at least one decode is on */
-    if ((PdoExtension->InterruptPin) && ((HaveMemSpace) || (HaveIoSpace)))
-    {
-         /* Read the interrupt line for the pin, check if it's valid */
-         InterruptLine = PdoExtension->AdjustedInterruptLine;
-         if ((InterruptLine) && (InterruptLine != -1))
-         {
-             /* Make sure there's still space */
-             ASSERT(Resource < LastResource);
-
-             /* Add the interrupt descriptor */
-             Resource->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
-             Resource->Type = CmResourceTypeInterrupt;
-             Resource->ShareDisposition = CmResourceShareShared;
-             Resource->u.Interrupt.Affinity = -1;
-             Resource->u.Interrupt.Level = InterruptLine;
-             Resource->u.Interrupt.Vector = InterruptLine;
-        }
-    }
-
-    /* Return the resouce list */
-    *Buffer = ResourceList;
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-PciQueryTargetDeviceRelations(IN PPCI_PDO_EXTENSION PdoExtension,
-                              IN OUT PDEVICE_RELATIONS *pDeviceRelations)
-{
-    PDEVICE_RELATIONS DeviceRelations;
-    PAGED_CODE();
-
-    /* If there were existing relations, free them */
-    if (*pDeviceRelations) ExFreePoolWithTag(*pDeviceRelations, 0);
-
-    /* Allocate a new structure for the relations */
-    DeviceRelations = ExAllocatePoolWithTag(NonPagedPool,
-                                            sizeof(DEVICE_RELATIONS),
-                                            'BicP');
-    if (!DeviceRelations) return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* Only one relation: the PDO */
-    DeviceRelations->Count = 1;
-    DeviceRelations->Objects[0] = PdoExtension->PhysicalDeviceObject;
-    ObReferenceObject(DeviceRelations->Objects[0]);
-
-    /* Return the new relations */
-    *pDeviceRelations = DeviceRelations;
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-PciQueryEjectionRelations(IN PPCI_PDO_EXTENSION PdoExtension,
-                          IN OUT PDEVICE_RELATIONS *pDeviceRelations)
-{
-    /* Not yet implemented */
-    UNIMPLEMENTED;
-    while (TRUE);
-}
-
-NTSTATUS
-NTAPI
-PciBuildRequirementsList(IN PPCI_PDO_EXTENSION PdoExtension,
-                         IN PPCI_COMMON_HEADER PciData,
-                         OUT PIO_RESOURCE_REQUIREMENTS_LIST* Buffer)
-{
-    PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
-    {
-        /* There aren't, so use the zero descriptor */
-        RequirementsList = PciZeroIoResourceRequirements;
-
-        /* Does it actually exist yet? */
-        if (!PciZeroIoResourceRequirements)
-        {
-            /* Allocate it, and use it for future use */
-            RequirementsList = PciAllocateIoRequirementsList(0, 0, 0);
-            PciZeroIoResourceRequirements = RequirementsList;
-            if (!PciZeroIoResourceRequirements) return STATUS_INSUFFICIENT_RESOURCES;
-        }
-
-        /* Return the zero requirements list to the caller */
-        *Buffer = RequirementsList;
-        DPRINT1("PCI - build resource reqs - early out, 0 resources\n");
-        return STATUS_SUCCESS;
-    }
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-PciQueryRequirements(IN PPCI_PDO_EXTENSION PdoExtension,
-                     IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *RequirementsList)
-{
-    NTSTATUS Status;
-    PCI_COMMON_HEADER PciHeader;
-    PAGED_CODE();
-
-    /* Check if the PDO has any resources, or at least an interrupt pin */
-    if ((PdoExtension->Resources) || (PdoExtension->InterruptPin))
-    {
-        /* Read the current PCI header */
-        PciReadDeviceConfig(PdoExtension, &PciHeader, 0, PCI_COMMON_HDR_LENGTH);
-
-        /* Use it to build a list of requirements */
-        Status = PciBuildRequirementsList(PdoExtension, &PciHeader, RequirementsList);
-        if (!NT_SUCCESS(Status)) return Status;
-
-        /* Is this a Compaq PCI Hotplug Controller (r17) on a PAE system ? */
-        if ((PciHeader.VendorID == 0xE11) &&
-            (PciHeader.DeviceID == 0xA0F7) &&
-            (PciHeader.RevisionID == 17) &&
-            (ExIsProcessorFeaturePresent(PF_PAE_ENABLED)))
-        {
-            /* Have not tested this on eVb's machine yet */
-            UNIMPLEMENTED;
-            while (TRUE);
-        }
-
-        /* Check if the requirements are actually the zero list */
-        if (*RequirementsList == PciZeroIoResourceRequirements)
-        {
-            /* A simple NULL will sufficie for the PnP Manager */
-            *RequirementsList = NULL;
-            DPRINT1("Returning NULL requirements list\n");
-        }
-        else
-        {
-            /* Otherwise, print out the requirements list */
-            PciDebugPrintIoResReqList(*RequirementsList);
-        }
-    }
-    else
-    {
-        /* There aren't any resources, so simply return NULL */
-        DPRINT1("PciQueryRequirements returning NULL requirements list\n");
-        *RequirementsList = NULL;
-    }
-
-    /* This call always succeeds (but maybe with no requirements) */
-    return STATUS_SUCCESS;
-}
-
-/*
- * 7. The IO/MEM/Busmaster decodes are disabled for the device.
- * 8. The PCI bus driver sets the operating mode bits of the Programming
- *    Interface byte to switch the controller to native mode.
- *
- *    Important: When the controller is set to native mode, it must quiet itself
- *    and must not decode I/O resources or generate interrupts until the operating
- *    system has enabled the ports in the PCI configuration header.
- *    The IO/MEM/BusMaster bits will be disabled before the mode change, but it
- *    is not possible to disable interrupts on the device. The device must not
- *    generate interrupts (either legacy or native mode) while the decodes are
- *    disabled in the command register.
- *
- *    This operation is expected to be instantaneous and the operating system does
- *    not stall afterward. It is also expected that the interrupt pin register in
- *    the PCI Configuration space for this device is accurate. The operating system
- *    re-reads this data after previously ignoring it.
- */
-BOOLEAN
-NTAPI
-PciConfigureIdeController(IN PPCI_PDO_EXTENSION PdoExtension,
-                          IN PPCI_COMMON_HEADER PciData,
-                          IN BOOLEAN Initial)
-{
-    UCHAR MasterMode, SlaveMode, MasterFixed, SlaveFixed, ProgIf, NewProgIf;
-    BOOLEAN Switched;
-    USHORT Command;
-
-    /* Assume it won't work */
-    Switched = FALSE;
-
-    /* Get master and slave current settings, and programmability flag */
-    ProgIf = PciData->ProgIf;
-    MasterMode = (ProgIf & 1) == 1;
-    MasterFixed = (ProgIf & 2) == 0;
-    SlaveMode = (ProgIf & 4) == 4;
-    SlaveFixed = (ProgIf & 8) == 0;
-
-    /*
-     * [..] In order for Windows XP SP1 and Windows Server 2003 to switch an ATA
-     * ATA controller from compatible mode to native mode, the following must be
-     * true:
-     *
-     * - The controller must indicate in its programming interface that both channels
-     *   can be switched to native mode. Windows XP SP1 and Windows Server 2003 do
-     *   not support switching only one IDE channel to native mode. See the PCI IDE
-     *   Controller Specification Revision 1.0 for details.
-     */
-    if ((MasterMode != SlaveMode) || (MasterFixed != SlaveFixed))
-    {
-        /* Windows does not support this configuration, fail */
-        DPRINT1("PCI: Warning unsupported IDE controller configuration for VEN_%04x&DEV_%04x!",
-                PdoExtension->VendorId,
-                PdoExtension->DeviceId);
-        return Switched;
-    }
-
-    /* Check if the controller is already in native mode */
-    if ((MasterMode) && (SlaveMode))
-    {
-        /* Check if I/O decodes should be disabled */
-        if ((Initial) || (PdoExtension->IoSpaceUnderNativeIdeControl))
-        {
-            /* Read the current command */
-            PciReadDeviceConfig(PdoExtension,
-                                &Command,
-                                FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                                sizeof(USHORT));
-
-            /* Disable I/O space decode */
-            Command &= ~PCI_ENABLE_IO_SPACE;
-
-            /* Update new command in PCI IDE controller */
-            PciWriteDeviceConfig(PdoExtension,
-                                 &Command,
-                                 FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                                 sizeof(USHORT));
-
-            /* Save updated command value */
-            PciData->Command = Command;
-        }
-
-        /* The controller is now in native mode */
-        Switched = TRUE;
-    }
-    else if (!(MasterFixed) &&
-             !(SlaveFixed) &&
-             (PdoExtension->BIOSAllowsIDESwitchToNativeMode) &&
-             !(PdoExtension->HackFlags & PCI_HACK_DISABLE_IDE_NATIVE_MODE))
-    {
-        /* Turn off decodes */
-        PciDecodeEnable(PdoExtension, FALSE, NULL);
-
-        /* Update the current command */
-        PciReadDeviceConfig(PdoExtension,
-                            &PciData->Command,
-                            FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                            sizeof(USHORT));
-
-        /* Enable native mode */
-        ProgIf = PciData->ProgIf | 5;
-        PciWriteDeviceConfig(PdoExtension,
-                             &ProgIf,
-                             FIELD_OFFSET(PCI_COMMON_HEADER, ProgIf),
-                             sizeof(UCHAR));
-
-        /* Verify the setting "stuck" */
-        PciReadDeviceConfig(PdoExtension,
-                            &NewProgIf,
-                            FIELD_OFFSET(PCI_COMMON_HEADER, ProgIf),
-                            sizeof(UCHAR));
-        if (NewProgIf == ProgIf)
-        {
-            /* Update the header and PDO data with the new programming mode */
-            PciData->ProgIf = ProgIf;
-            PdoExtension->ProgIf = NewProgIf;
-
-            /* Clear the first four BARs to reset current BAR setttings */
-            PciData->u.type0.BaseAddresses[0] = 0;
-            PciData->u.type0.BaseAddresses[1] = 0;
-            PciData->u.type0.BaseAddresses[2] = 0;
-            PciData->u.type0.BaseAddresses[3] = 0;
-            PciWriteDeviceConfig(PdoExtension,
-                                 PciData->u.type0.BaseAddresses,
-                                 FIELD_OFFSET(PCI_COMMON_HEADER,
-                                              u.type0.BaseAddresses),
-                                 4 * sizeof(ULONG));
-
-            /* Re-read the BARs to have the latest data for native mode IDE */
-            PciReadDeviceConfig(PdoExtension,
-                                PciData->u.type0.BaseAddresses,
-                                FIELD_OFFSET(PCI_COMMON_HEADER,
-                                             u.type0.BaseAddresses),
-                                4 * sizeof(ULONG));
-
-            /* Re-read the interrupt pin used for native mode IDE */
-            PciReadDeviceConfig(PdoExtension,
-                                &PciData->u.type0.InterruptPin,
-                                FIELD_OFFSET(PCI_COMMON_HEADER,
-                                             u.type0.InterruptPin),
-                                sizeof(UCHAR));
-
-            /* The IDE Controller is now in native mode */
-            Switched = TRUE;
-        }
-        else
-        {
-            /* Settings did not work, fail */
-            DPRINT1("PCI: Warning failed switch to native mode for IDE controller VEN_%04x&DEV_%04x!",
-                    PciData->VendorID,
-                    PciData->DeviceID);
-        }
-   }
-
-   /* Return whether or not native mode was enabled on the IDE controller */
-   return Switched;
-}
-
-VOID
-NTAPI
-PciApplyHacks(IN PPCI_FDO_EXTENSION DeviceExtension,
-              IN PPCI_COMMON_HEADER PciData,
-              IN PCI_SLOT_NUMBER SlotNumber,
-              IN ULONG OperationType,
-              PPCI_PDO_EXTENSION PdoExtension)
-{
-    ULONG LegacyBaseAddress;
-    USHORT Command;
-    UCHAR RegValue;
-
-    /* Check what kind of hack operation this is */
-    switch (OperationType)
-    {
-        /*
-         * This is mostly concerned with fixing up incorrect class data that can
-         * exist on certain PCI hardware before the 2.0 spec was ratified.
-         */
-        case PCI_HACK_FIXUP_BEFORE_CONFIGURATION:
-
-            /* Note that the i82375 PCI/EISA and the i82378 PCI/ISA bridges that
-             * are present on certain DEC/NT Alpha machines are pre-PCI 2.0 devices
-             * and appear as non-classified, so their correct class/subclass data
-             * is written here instead.
-             */
-            if ((PciData->VendorID == 0x8086) &&
-                ((PciData->DeviceID == 0x482) || (PciData->DeviceID == 0x484)))
-            {
-                /* Note that 0x482 is the i82375 (EISA), 0x484 is the i82378 (ISA) */
-                PciData->SubClass = PciData->DeviceID == 0x482 ?
-                                    PCI_SUBCLASS_BR_EISA : PCI_SUBCLASS_BR_ISA;
-                PciData->BaseClass = PCI_CLASS_BRIDGE_DEV;
-
-                /*
-                 * Because the software is modifying the actual header data from
-                 * the BIOS, this flag tells the driver to ignore failures when
-                 * comparing the original BIOS data with the PCI data.
-                 */
-                if (PdoExtension) PdoExtension->ExpectedWritebackFailure = TRUE;
-            }
-
-            /* Note that in this case, an immediate return is issued */
-            return;
-
-        /*
-         * This is concerned with setting up interrupts correctly for native IDE
-         * mode, but will also handle broken VGA decoding on older bridges as
-         * well as a PAE-specific hack for certain Compaq Hot-Plug Controllers.
-         */
-        case PCI_HACK_FIXUP_AFTER_CONFIGURATION:
-
-            /* There should always be a PDO extension passed in */
-            ASSERT(PdoExtension);
-
-            /*
-             * On the OPTi Viper-M IDE controller, Linux doesn't support IDE-DMA
-             * and FreeBSD bug reports indicate that the system crashes when the
-             * feature is enabled (so it's disabled on that OS as well). In the
-             * NT PCI Bus Driver, it seems Microsoft too, completely disables
-             * Native IDE functionality on this controller, so it would seem OPTi
-             * simply frelled up this controller.
-             */
-            if ((PciData->VendorID == 0x1045) && (PciData->DeviceID != 0xC621))
-            {
-                /* Disable native mode */
-                PciData->ProgIf &= ~5;
-                PciData->u.type0.InterruptPin = 0;
-
-                /*
-                 * Because the software is modifying the actual header data from
-                 * the BIOS, this flag tells the driver to ignore failures when
-                 * comparing the original BIOS data with the PCI data.
-                 */
-                PdoExtension->ExpectedWritebackFailure = TRUE;
-            }
-            else if ((PciData->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
-                    (PciData->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
-            {
-                /* For other IDE controllers, start out in compatible mode */
-                PdoExtension->BIOSAllowsIDESwitchToNativeMode = FALSE;
-
-                /*
-                 * Registry must have enabled native mode (typically as a result
-                 * of an INF file directive part of the IDE controller's driver)
-                 * and the system must not be booted in Safe Mode. If that checks
-                 * out, then evaluate the ACPI NATA method to see if the platform
-                 * supports this. See the section "BIOS and Platform Prerequisites
-                 * for Switching a Native-Mode-Capable Controller" in the Storage
-                 * section of the Windows Driver Kit for more details:
-                 *
-                 * 5. For each ATA controller enumerated, the PCI bus driver checks
-                 *    the Programming Interface register of the IDE controller to
-                 *    see if it supports switching both channels to native mode.
-                 * 6. The PCI bus driver checks whether the BIOS/platform supports
-                 *    switching the controller by checking the NATA method described
-                 *    earlier in this article.
-                 *
-                 *    If an ATA controller does not indicate that it is native
-                 *    mode-capable, or if the BIOS NATA control method is missing
-                 *    or does not list that device, the PCI bus driver does not
-                 *    switch the controller and it is assigned legacy resources.
-                 *
-                 *  If both the controller and the BIOS indicate that the controller
-                 *  can be switched, the process of switching the controller begins
-                 *  with the next step.
-                 */
-                if ((PciEnableNativeModeATA) &&
-                    !(InitSafeBootMode) &&
-                    (PciIsSlotPresentInParentMethod(PdoExtension, 'ATAN')))
-                {
-                    /* The platform supports it, remember that */
-                    PdoExtension->BIOSAllowsIDESwitchToNativeMode = TRUE;
-
-                    /*
-                     * Now switch the controller into native mode if both channels
-                     * support native IDE mode. See "How Windows Switches an ATA
-                     * Controller to Native Mode" in the Storage section of the
-                     * Windows Driver Kit for more details.
-                     */
-                    PdoExtension->IDEInNativeMode =
-                        PciConfigureIdeController(PdoExtension, PciData, TRUE);
-                }
-
-                /* Is native mode enabled after all? */
-                if ((PciData->ProgIf & 5) != 5)
-                {
-                    /* Compatible mode, so force ISA-style IRQ14 and IRQ 15 */
-                    PciData->u.type0.InterruptPin = 0;
-                }
-            }
-
-            /* Is this a PCI device with legacy VGA card decodes on the root bus? */
-            if ((PdoExtension->HackFlags & PCI_HACK_VIDEO_LEGACY_DECODE) &&
-                (PCI_IS_ROOT_FDO(DeviceExtension)) &&
-                !(DeviceExtension->BrokenVideoHackApplied))
-            {
-                /* Tell the arbiter to apply a hack for these older devices */
-                ario_ApplyBrokenVideoHack(DeviceExtension);
-            }
-
-            /* Is this a Compaq PCI Hotplug Controller (r17) on a PAE system ? */
-            if ((PciData->VendorID == 0xE11) &&
-                (PciData->DeviceID == 0xA0F7) &&
-                (PciData->RevisionID == 17) &&
-                (ExIsProcessorFeaturePresent(PF_PAE_ENABLED)))
-            {
-                /* Turn off the decodes immediately */
-                PciData->Command &= ~(PCI_ENABLE_IO_SPACE |
-                                      PCI_ENABLE_MEMORY_SPACE |
-                                      PCI_ENABLE_BUS_MASTER);
-                PciWriteDeviceConfig(PdoExtension,
-                                     &PciData->Command,
-                                     FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                                     sizeof(USHORT));
-
-                /* Do not EVER turn them on again, this will blow up the system */
-                PdoExtension->CommandEnables &= ~(PCI_ENABLE_IO_SPACE |
-                                                  PCI_ENABLE_MEMORY_SPACE |
-                                                  PCI_ENABLE_BUS_MASTER);
-                PdoExtension->HackFlags |= PCI_HACK_PRESERVE_COMMAND;
-            }
-            break;
-
-        /*
-         * This is called whenever resources are changed and hardware needs to be
-         * updated. It is concerned with two highly specific erratas on an IBM
-         * hot-plug docking bridge used on the Thinkpad 600 Series and on Intel's
-         * ICH PCI Bridges.
-         */
-        case PCI_HACK_FIXUP_BEFORE_UPDATE:
-
-            /* There should always be a PDO extension passed in */
-            ASSERT(PdoExtension);
-
-            /* Is this an IBM 20H2999 PCI Docking Bridge, used on Thinkpads? */
-            if ((PdoExtension->VendorId == 0x1014) &&
-                (PdoExtension->DeviceId == 0x95))
-            {
-                /* Read the current command */
-                PciReadDeviceConfig(PdoExtension,
-                                    &Command,
-                                    FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                                    sizeof(USHORT));
-
-                /* Turn off the decodes */
-                PciDecodeEnable(PdoExtension, FALSE, &Command);
-
-                /* Apply the required IBM workaround */
-                PciReadDeviceConfig(PdoExtension, &RegValue, 0xE0, sizeof(UCHAR));
-                RegValue &= ~2;
-                RegValue |= 1;
-                PciWriteDeviceConfig(PdoExtension, &RegValue, 0xE0, sizeof(UCHAR));
-
-                /* Restore the command to its original value */
-                PciWriteDeviceConfig(PdoExtension,
-                                     &Command,
-                                     FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                                     sizeof(USHORT));
-
-            }
-
-            /*
-             * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
-             * i820, i840, i845 Chipsets) that have subtractive decode enabled,
-             * and whose hack flags do not specifiy that this support is broken.
-             */
-            if ((PdoExtension->HeaderType == PCI_BRIDGE_TYPE) &&
-                (PdoExtension->Dependent.type1.SubtractiveDecode) &&
-                ((PdoExtension->VendorId == 0x8086) &&
-                 ((PdoExtension->DeviceId == 0x2418) ||
-                  (PdoExtension->DeviceId == 0x2428) ||
-                  (PdoExtension->DeviceId == 0x244E) ||
-                  (PdoExtension->DeviceId == 0x2448))) &&
-               !(PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
-            {
-                /*
-                 * The positive decode window shouldn't be used, these values are
-                 * normally all read-only or initialized to 0 by the BIOS, but
-                 * it appears Intel doesn't do this, so the PCI Bus Driver will
-                 * do it in software instead. Note that this is used to prevent
-                 * certain non-compliant PCI devices from breaking down due to the
-                 * fact that these ICH bridges have a known "quirk" (which Intel
-                 * documents as a known "erratum", although it's not not really
-                 * an ICH bug since the PCI specification does allow for it) in
-                 * that they will sometimes send non-zero addresses during special
-                 * cycles (ie: non-zero data during the address phase). These
-                 * broken PCI cards will mistakenly attempt to claim the special
-                 * cycle and corrupt their I/O and RAM ranges. Again, in Intel's
-                 * defense, the PCI specification only requires stable data, not
-                 * necessarily zero data, during the address phase.
-                 */
-                PciData->u.type1.MemoryBase = 0xFFFF;
-                PciData->u.type1.PrefetchBase = 0xFFFF;
-                PciData->u.type1.IOBase = 0xFF;
-                PciData->u.type1.IOLimit = 0;
-                PciData->u.type1.MemoryLimit = 0;
-                PciData->u.type1.PrefetchLimit = 0;
-                PciData->u.type1.PrefetchBaseUpper32 = 0;
-                PciData->u.type1.PrefetchLimitUpper32 = 0;
-                PciData->u.type1.IOBaseUpper16 = 0;
-                PciData->u.type1.IOLimitUpper16 = 0;
-            }
-            break;
-
-        default:
-            return;
-    }
-
-    /* Finally, also check if this is this a CardBUS device? */
-    if (PCI_CONFIGURATION_TYPE(PciData) == PCI_CARDBUS_BRIDGE_TYPE)
-    {
-        /*
-         * At offset 44h the LegacyBaseAddress is stored, which is cleared by
-         * ACPI-aware versions of Windows, to disable legacy-mode I/O access to
-         * CardBus controllers. For more information, see "Supporting CardBus
-         * Controllers under ACPI" in the "CardBus Controllers and Windows"
-         * Whitepaper on WHDC.
-         */
-        LegacyBaseAddress = 0;
-        PciWriteDeviceConfig(PdoExtension,
-                             &LegacyBaseAddress,
-                             sizeof(PCI_COMMON_HEADER) + sizeof(ULONG),
-                             sizeof(ULONG));
-    }
-}
-
-BOOLEAN
-NTAPI
-PcipIsSameDevice(IN PPCI_PDO_EXTENSION DeviceExtension,
-                 IN PPCI_COMMON_HEADER PciData)
-{
-    BOOLEAN IdMatch, RevMatch, SubsysMatch;
-    ULONGLONG HackFlags = DeviceExtension->HackFlags;
-
-    /* Check if the IDs match */
-    IdMatch = (PciData->VendorID == DeviceExtension->VendorId) &&
-              (PciData->DeviceID == DeviceExtension->DeviceId);
-    if (!IdMatch) return FALSE;
-
-    /* If the device has a valid revision, check if it matches */
-    RevMatch = (HackFlags & PCI_HACK_NO_REVISION_AFTER_D3) ||
-               (PciData->RevisionID == DeviceExtension->RevisionId);
-    if (!RevMatch) return FALSE;
-
-    /* For multifunction devices, this is enough to assume they're the same */
-    if (PCI_MULTIFUNCTION_DEVICE(PciData)) return TRUE;
-
-    /* For bridge devices, there's also nothing else that can be checked */
-    if (DeviceExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) return TRUE;
-
-    /* Devices, on the other hand, have subsystem data that can be compared */
-    SubsysMatch = (HackFlags & (PCI_HACK_NO_SUBSYSTEM |
-                                PCI_HACK_NO_SUBSYSTEM_AFTER_D3)) ||
-                  ((DeviceExtension->SubsystemVendorId ==
-                    PciData->u.type0.SubVendorID) &&
-                   (DeviceExtension->SubsystemId ==
-                    PciData->u.type0.SubSystemID));
-    return SubsysMatch;
-}
-
-BOOLEAN
-NTAPI
-PciSkipThisFunction(IN PPCI_COMMON_HEADER PciData,
-                    IN PCI_SLOT_NUMBER Slot,
-                    IN UCHAR OperationType,
-                    IN ULONGLONG HackFlags)
-{
-    do
-    {
-        /* Check if this is device enumeration */
-        if (OperationType == PCI_SKIP_DEVICE_ENUMERATION)
-        {
-            /* Check if there's a hackflag saying not to enumerate this device */
-            if (HackFlags & PCI_HACK_NO_ENUM_AT_ALL) break;
-
-            /* Check if this is the high end of a double decker device */
-            if ((HackFlags & PCI_HACK_DOUBLE_DECKER) &&
-                (Slot.u.bits.DeviceNumber >= 16))
-            {
-                /* It belongs to the same device, so skip it */
-                DPRINT1("    Device (Ven %04x Dev %04x (d=0x%x, f=0x%x)) is a ghost.\n",
-                        PciData->VendorID,
-                        PciData->DeviceID,
-                        Slot.u.bits.DeviceNumber,
-                        Slot.u.bits.FunctionNumber);
-                break;
-            }
-        }
-        else if (OperationType == PCI_SKIP_RESOURCE_ENUMERATION)
-        {
-            /* Resource enumeration, check for a hackflag saying not to do it */
-            if (HackFlags & PCI_HACK_ENUM_NO_RESOURCE) break;
-        }
-        else
-        {
-            /* Logic error in the driver */
-            ASSERTMSG(FALSE, "PCI Skip Function - Operation type unknown.");
-        }
-
-        /* Check for legacy bridges during resource enumeration */
-        if ((PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
-            (PciData->SubClass <= PCI_SUBCLASS_BR_MCA) &&
-            (OperationType == PCI_SKIP_RESOURCE_ENUMERATION))
-        {
-            /* Their resources are not enumerated, only PCI and Cardbus/PCMCIA */
-            break;
-        }
-        else if (PciData->BaseClass == PCI_CLASS_NOT_DEFINED)
-        {
-            /* Undefined base class (usually a PCI BIOS/ROM bug) */
-            DPRINT1("    Vendor %04x, Device %04x has class code of PCI_CLASS_NOT_DEFINED\n",
-                    PciData->VendorID,
-                    PciData->DeviceID);
-
-            /*
-             * The Alder has an Intel Extended Express System Support Controller
-             * which presents apparently spurious BARs. When the PCI resource
-             * code tries to reassign these BARs, the second IO-APIC gets
-             * disabled (with disastrous consequences). The first BAR is the
-             * actual IO-APIC, the remaining five bars seem to be spurious
-             * resources, so ignore this device completely.
-             */
-            if ((PciData->VendorID == 0x8086) && (PciData->DeviceID == 8)) break;
-        }
-
-        /* Other normal PCI cards and bridges are enumerated */
-        if (PCI_CONFIGURATION_TYPE(PciData) <= PCI_CARDBUS_BRIDGE_TYPE) return FALSE;
-    } while (FALSE);
-
-    /* Hit one of the known bugs/hackflags, or this is a new kind of PCI unit */
-    DPRINT1("   Device skipped (not enumerated).\n");
-    return TRUE;
-}
-
-VOID
-NTAPI
-PciGetEnhancedCapabilities(IN PPCI_PDO_EXTENSION PdoExtension,
-                           IN PPCI_COMMON_HEADER PciData)
-{
-    ULONG HeaderType, CapPtr, TargetAgpCapabilityId;
-    DEVICE_POWER_STATE WakeLevel;
-    PCI_CAPABILITIES_HEADER AgpCapability;
-    PCI_PM_CAPABILITY PowerCapabilities;
-    PAGED_CODE();
-
-    /* Assume no known wake level */
-    PdoExtension->PowerState.DeviceWakeLevel = PowerDeviceUnspecified;
-
-    /* Make sure the device has capabilities */
-    if (!(PciData->Status & PCI_STATUS_CAPABILITIES_LIST))
-    {
-        /* If it doesn't, there will be no power management */
-        PdoExtension->CapabilitiesPtr = 0;
-        PdoExtension->HackFlags |= PCI_HACK_NO_PM_CAPS;
-    }
-    else
-    {
-        /* There's capabilities, need to figure out where to get the offset */
-        HeaderType = PCI_CONFIGURATION_TYPE(PciData);
-        if (HeaderType == PCI_CARDBUS_BRIDGE_TYPE)
-        {
-            /* Use the bridge's header */
-            CapPtr = PciData->u.type2.CapabilitiesPtr;
-        }
-        else
-        {
-            /* Use the device header */
-            ASSERT(HeaderType <= PCI_CARDBUS_BRIDGE_TYPE);
-            CapPtr = PciData->u.type0.CapabilitiesPtr;
-        }
-
-        /* Make sure the pointer is spec-aligned and located, and save it */
-        DPRINT1("Device has capabilities at: %lx\n", CapPtr);
-        ASSERT(((CapPtr & 0x3) == 0) && (CapPtr >= PCI_COMMON_HDR_LENGTH));
-        PdoExtension->CapabilitiesPtr = CapPtr;
-
-        /* Check for PCI-to-PCI Bridges and AGP bridges */
-        if ((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
-            ((PdoExtension->SubClass == PCI_SUBCLASS_BR_HOST) ||
-             (PdoExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI)))
-        {
-            /* Query either the raw AGP capabilitity, or the Target AGP one */
-            TargetAgpCapabilityId = (PdoExtension->SubClass ==
-                                     PCI_SUBCLASS_BR_PCI_TO_PCI) ?
-                                     PCI_CAPABILITY_ID_AGP_TARGET :
-                                     PCI_CAPABILITY_ID_AGP;
-            if (PciReadDeviceCapability(PdoExtension,
-                                        PdoExtension->CapabilitiesPtr,
-                                        TargetAgpCapabilityId,
-                                        &AgpCapability,
-                                        sizeof(PCI_CAPABILITIES_HEADER)))
-            {
-                /* AGP target ID was found, store it */
-                DPRINT1("AGP ID: %lx\n", TargetAgpCapabilityId);
-                PdoExtension->TargetAgpCapabilityId = TargetAgpCapabilityId;
-            }
-        }
-
-        /* Check for devices that are known not to have proper power management */
-        if (!(PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS))
-        {
-            /* Query if this device supports power management */
-            if (!PciReadDeviceCapability(PdoExtension,
-                                         PdoExtension->CapabilitiesPtr,
-                                         PCI_CAPABILITY_ID_POWER_MANAGEMENT,
-                                         &PowerCapabilities.Header,
-                                         sizeof(PCI_PM_CAPABILITY)))
-            {
-                /* No power management, so act as if it had the hackflag set */
-                DPRINT1("No PM caps, disabling PM\n");
-                PdoExtension->HackFlags |= PCI_HACK_NO_PM_CAPS;
-            }
-            else
-            {
-                /* Otherwise, pick the highest wake level that is supported */
-                WakeLevel = PowerDeviceUnspecified;
-                if (PowerCapabilities.PMC.Capabilities.Support.PMED0)
-                    WakeLevel = PowerDeviceD0;
-                if (PowerCapabilities.PMC.Capabilities.Support.PMED1)
-                    WakeLevel = PowerDeviceD1;
-                if (PowerCapabilities.PMC.Capabilities.Support.PMED2)
-                    WakeLevel = PowerDeviceD2;
-                if (PowerCapabilities.PMC.Capabilities.Support.PMED3Hot)
-                    WakeLevel = PowerDeviceD3;
-                if (PowerCapabilities.PMC.Capabilities.Support.PMED3Cold)
-                    WakeLevel = PowerDeviceD3;
-                PdoExtension->PowerState.DeviceWakeLevel = WakeLevel;
-
-                /* Convert the PCI power state to the NT power state */
-                PdoExtension->PowerState.CurrentDeviceState =
-                    PowerCapabilities.PMCSR.ControlStatus.PowerState + 1;
-
-                /* Save all the power capabilities */
-                PdoExtension->PowerCapabilities = PowerCapabilities.PMC.Capabilities;
-                DPRINT1("PM Caps Found! Wake Level: %d Power State: %d\n",
-                        WakeLevel, PdoExtension->PowerState.CurrentDeviceState);
-            }
-        }
-    }
-
-    /* At the very end of all this, does this device not have power management? */
-    if (PdoExtension->HackFlags & PCI_HACK_NO_PM_CAPS)
-    {
-        /* Then guess the current state based on whether the decodes are on */
-        PdoExtension->PowerState.CurrentDeviceState =
-            PciData->Command & (PCI_ENABLE_IO_SPACE |
-                                PCI_ENABLE_MEMORY_SPACE |
-                                PCI_ENABLE_BUS_MASTER) ?
-            PowerDeviceD0: PowerDeviceD3;
-        DPRINT1("PM is off, so assumed device is: %d based on enables\n",
-                PdoExtension->PowerState.CurrentDeviceState);
-    }
-}
-
-VOID
-NTAPI
-PciWriteLimitsAndRestoreCurrent(IN PVOID Reserved,
-                                IN PVOID Context2)
-{
-    PPCI_CONFIGURATOR_CONTEXT Context = Context2;
-    PPCI_COMMON_HEADER PciData, Current;
-    PPCI_PDO_EXTENSION PdoExtension;
-
-    /* Grab all parameters from the context */
-    PdoExtension = Context->PdoExtension;
-    Current = Context->Current;
-    PciData = Context->PciData;
-
-    /* Write the limit discovery header */
-    PciWriteDeviceConfig(PdoExtension, PciData, 0, PCI_COMMON_HDR_LENGTH);
-
-    /* Now read what the device indicated the limits are */
-    PciReadDeviceConfig(PdoExtension, PciData, 0, PCI_COMMON_HDR_LENGTH);
-
-    /* Then write back the original configuration header */
-    PciWriteDeviceConfig(PdoExtension, Current, 0, PCI_COMMON_HDR_LENGTH);
-
-    /* Copy back the original command that was saved in the context */
-    Current->Command = Context->Command;
-    if (Context->Command)
-    {
-        /* Program it back into the device */
-        PciWriteDeviceConfig(PdoExtension,
-                             &Context->Command,
-                             FIELD_OFFSET(PCI_COMMON_HEADER, Command),
-                             sizeof(USHORT));
-    }
-
-    /* Copy back the original status that was saved as well */
-    Current->Status = Context->Status;
-
-    /* Call the configurator to restore any other data that might've changed */
-    Context->Configurator->RestoreCurrent(Context);
-}
-
-NTSTATUS
-NTAPI
-PcipGetFunctionLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
-{
-    PPCI_CONFIGURATOR Configurator;
-    PPCI_COMMON_HEADER PciData, Current;
-    PPCI_PDO_EXTENSION PdoExtension;
-    PCI_IPI_CONTEXT IpiContext;
-    PIO_RESOURCE_DESCRIPTOR IoDescriptor;
-    ULONG Offset;
-    PAGED_CODE();
-
-    /* Grab all parameters from the context */
-    PdoExtension = Context->PdoExtension;
-    Current = Context->Current;
-    PciData = Context->PciData;
-
-    /* Save the current PCI Command and Status word */
-    Context->Status = Current->Status;
-    Context->Command = Current->Command;
-
-    /* Now that they're saved, clear the status, and disable all decodes */
-    Current->Status = 0;
-    Current->Command &= ~(PCI_ENABLE_IO_SPACE |
-                          PCI_ENABLE_MEMORY_SPACE |
-                          PCI_ENABLE_BUS_MASTER);
-
-    /* Make a copy of the current PCI configuration header (with decodes off) */
-    RtlCopyMemory(PciData, Current, PCI_COMMON_HDR_LENGTH);
-
-    /* Locate the correct resource configurator for this type of device */
-    Configurator = &PciConfigurators[PdoExtension->HeaderType];
-    Context->Configurator = Configurator;
-
-    /* Initialize it, which will typically setup the BARs for limit discovery */
-    Configurator->Initialize(Context);
-
-    /* Check for critical devices and PCI Debugging devices */
-    if ((PdoExtension->HackFlags & PCI_HACK_CRITICAL_DEVICE) ||
-        (PdoExtension->OnDebugPath))
-    {
-        /* Specifically check for a PCI Debugging device */
-        if (PdoExtension->OnDebugPath)
-        {
-            /* Was it enabled for bus mastering? */
-            if (Context->Command & PCI_ENABLE_BUS_MASTER)
-            {
-                /* This decode needs to be re-enabled so debugging can work */
-                PciData->Command |= PCI_ENABLE_BUS_MASTER;
-                Current->Command |= PCI_ENABLE_BUS_MASTER;
-            }
-
-            /* Disable the debugger while the discovery is happening */
-            KdDisableDebugger();
-        }
-
-        /* For these devices, an IPI must be sent to force high-IRQL discovery */
-        IpiContext.Barrier = 1;
-        IpiContext.RunCount = 1;
-        IpiContext.DeviceExtension = PdoExtension;
-        IpiContext.Function = PciWriteLimitsAndRestoreCurrent;
-        IpiContext.Context = Context;
-        KeIpiGenericCall(PciExecuteCriticalSystemRoutine, (ULONG_PTR)&IpiContext);
-
-        /* Re-enable the debugger if this was a PCI Debugging Device */
-        if (PdoExtension->OnDebugPath) KdEnableDebugger();
-    }
-    else
-    {
-        /* Otherwise, it's safe to do this in-line at low IRQL */
-        PciWriteLimitsAndRestoreCurrent(PdoExtension, Context);
-    }
-
-    /*
-     * Check if it's valid to compare the headers to see if limit discovery mode
-     * has properly exited (the expected case is that the PCI header would now
-     * be equal to what it was before). In some cases, it is known that this will
-     * fail, because during PciApplyHacks (among other places), software hacks
-     * had to be applied to the header, which the hardware-side will not see, and
-     * thus the headers would appear "different".
-     */
-    if (!PdoExtension->ExpectedWritebackFailure)
-    {
-        /* Read the current PCI header now, after discovery has completed */
-        PciReadDeviceConfig(PdoExtension, PciData + 1, 0, PCI_COMMON_HDR_LENGTH);
-
-        /* Check if the current header at entry, is equal to the header now */
-        Offset = RtlCompareMemory(PciData + 1, Current, PCI_COMMON_HDR_LENGTH);
-        if (Offset != PCI_COMMON_HDR_LENGTH)
-        {
-            /* It's not, which means configuration somehow changed, dump this */
-            DPRINT1("PCI - CFG space write verify failed at offset 0x%x\n", Offset);
-            PciDebugDumpCommonConfig(PciData + 1);
-            DPRINT1("----------\n");
-            PciDebugDumpCommonConfig(Current);
-        }
-    }
-
-    /* This PDO should not already have resources, since this is only done once */
-    ASSERT(PdoExtension->Resources == NULL);
-
-    /* Allocate the structure that will hold the discovered resources and limits */
-    PdoExtension->Resources = ExAllocatePoolWithTag(NonPagedPool,
-                                                    sizeof(PCI_FUNCTION_RESOURCES),
-                                                    'BicP');
-    if (!PdoExtension->Resources) return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* Clear it out for now */
-    RtlZeroMemory(PdoExtension->Resources, sizeof(PCI_FUNCTION_RESOURCES));
-
-    /* Now call the configurator, which will first store the limits... */
-    Configurator->SaveLimits(Context);
-
-    /* ...and then store the current resources being used */
-    Configurator->SaveCurrentSettings(Context);
-
-    /* Loop all the limit descriptors backwards */
-    IoDescriptor = &PdoExtension->Resources->Limit[PCI_TYPE0_ADDRESSES + 1];
-    while (TRUE)
-    {
-        /* Keep going until a non-null descriptor is found */
-        IoDescriptor--;
-        if (IoDescriptor->Type != CmResourceTypeNull) break;
-
-        /* This is a null descriptor, is it the last one? */
-        if (IoDescriptor == &PdoExtension->Resources->Limit[PCI_TYPE0_ADDRESSES + 1])
-        {
-            /* This means the descriptor is NULL, which means discovery failed */
-            DPRINT1("PCI Resources fail!\n");
-
-            /* No resources will be assigned for the device */
-            ExFreePoolWithTag(PdoExtension->Resources, 0);
-            PdoExtension->Resources = NULL;
-            break;
-        }
-    }
-
-    /* Return success here, even if the device has no assigned resources */
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-PciGetFunctionLimits(IN PPCI_PDO_EXTENSION PdoExtension,
-                     IN PPCI_COMMON_HEADER Current,
-                     IN ULONGLONG HackFlags)
-{
-    NTSTATUS Status;
-    PPCI_COMMON_HEADER PciData;
-    PCI_CONFIGURATOR_CONTEXT Context;
-    PAGED_CODE();
-
-    /* Do the hackflags indicate this device should be skipped? */
-    if (PciSkipThisFunction(Current,
-                            PdoExtension->Slot,
-                            PCI_SKIP_RESOURCE_ENUMERATION,
-                            HackFlags))
-    {
-        /* Do not process its resources */
-        return STATUS_SUCCESS;
-    }
-
-    /* Allocate a buffer to hold two PCI configuration headers */
-    PciData = ExAllocatePoolWithTag(0, 2 * PCI_COMMON_HDR_LENGTH, 'BicP');
-    if (!PciData) return STATUS_INSUFFICIENT_RESOURCES;
-
-    /* Set up the context for the resource enumeration, and do it */
-    Context.Current = Current;
-    Context.PciData = PciData;
-    Context.PdoExtension = PdoExtension;
-    Status = PcipGetFunctionLimits(&Context);
-
-    /* Enumeration is completed, free the PCI headers and return the status */
-    ExFreePoolWithTag(PciData, 0);
-    return Status;
-}
-
-VOID
-NTAPI
-PciProcessBus(IN PPCI_FDO_EXTENSION DeviceExtension)
-{
-    PPCI_PDO_EXTENSION PdoExtension;
-    PDEVICE_OBJECT PhysicalDeviceObject;
-    PAGED_CODE();
-
-    /* Get the PDO Extension */
-    PhysicalDeviceObject = DeviceExtension->PhysicalDeviceObject;
-    PdoExtension = (PPCI_PDO_EXTENSION)PhysicalDeviceObject->DeviceExtension;
-
-    /* Cheeck if this is the root bus */
-    if (!PCI_IS_ROOT_FDO(DeviceExtension))
-    {
-        /* Not really handling this year */
-        UNIMPLEMENTED;
-        while (TRUE);
-
-        /* Check for PCI bridges with the ISA bit set, or required */
-        if ((PdoExtension) &&
-            (PciClassifyDeviceType(PdoExtension) == PciTypePciBridge) &&
-            ((PdoExtension->Dependent.type1.IsaBitRequired) ||
-             (PdoExtension->Dependent.type1.IsaBitSet)))
-        {
-            /* We'll need to do some legacy support */
-            UNIMPLEMENTED;
-            while (TRUE);
-        }
-    }
-    else
-    {
-        /* Scan all of the root bus' children bridges */
-        for (PdoExtension = DeviceExtension->ChildBridgePdoList;
-             PdoExtension;
-             PdoExtension = PdoExtension->NextBridge)
-        {
-            /* Find any that have the VGA decode bit on */
-            if (PdoExtension->Dependent.type1.VgaBitSet)
-            {
-                /* Again, some more legacy support we'll have to do */
-                UNIMPLEMENTED;
-                while (TRUE);
-            }
-        }
-    }
-
-    /* Check for ACPI systems where the OS assigns bus numbers */
-    if (PciAssignBusNumbers)
-    {
-        /* Not yet supported */
-        UNIMPLEMENTED;
-        while (TRUE);
-    }
-}
-
-NTSTATUS
-NTAPI
-PciScanBus(IN PPCI_FDO_EXTENSION DeviceExtension)
-{
-    ULONG MaxDevice = PCI_MAX_DEVICES;
-    BOOLEAN ProcessFlag = FALSE;
-    ULONG i, j, k, Size;
-    USHORT CapOffset, TempOffset;
-    LONGLONG HackFlags;
-    PDEVICE_OBJECT DeviceObject;
-    UCHAR Buffer[PCI_COMMON_HDR_LENGTH];
-    UCHAR BiosBuffer[PCI_COMMON_HDR_LENGTH];
-    PPCI_COMMON_HEADER PciData = (PVOID)Buffer;
-    PPCI_COMMON_HEADER BiosData = (PVOID)BiosBuffer;
-    PCI_SLOT_NUMBER PciSlot;
-    PCHAR Name;
-    NTSTATUS Status;
-    PPCI_PDO_EXTENSION PdoExtension, NewExtension;
-    PPCI_PDO_EXTENSION* BridgeExtension;
-    PWCHAR DescriptionText;
-    USHORT SubVendorId, SubSystemId;
-    PCI_CAPABILITIES_HEADER CapHeader, PcixCapHeader;
-    UCHAR SecondaryBus;
-    DPRINT1("PCI Scan Bus: FDO Extension @ 0x%x, Base Bus = 0x%x\n",
-            DeviceExtension, DeviceExtension->BaseBus);
-
-    /* Is this the root FDO? */
-    if (!PCI_IS_ROOT_FDO(DeviceExtension))
-    {
-        /* Get the PDO for the child bus */
-        PdoExtension = DeviceExtension->PhysicalDeviceObject->DeviceExtension;
-        ASSERT_PDO(PdoExtension);
-
-        /* Check for hack which only allows bus to have one child device */
-        if (PdoExtension->HackFlags & PCI_HACK_ONE_CHILD) MaxDevice = 1;
-      
-        /* Check if the secondary bus number has changed */
-        PciReadDeviceConfig(PdoExtension,
-                            &SecondaryBus,
-                            FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.SecondaryBus),
-                            sizeof(UCHAR));
-        if (SecondaryBus != PdoExtension->Dependent.type1.SecondaryBus)
-        {
-            DPRINT1("PCI: Bus numbers have been changed!  Restoring originals.\n");
-            UNIMPLEMENTED;
-            while (TRUE);
-        }
-    }
-
-    /* Loop every device on the bus */
-    PciSlot.u.bits.Reserved = 0;
-    i = DeviceExtension->BaseBus;
-    for (j = 0; j < MaxDevice; j++)
-    {
-        /* Loop every function of each device */
-        PciSlot.u.bits.DeviceNumber = j;
-        for (k = 0; k < PCI_MAX_FUNCTION; k++)
-        {
-            /* Build the final slot structure */
-            PciSlot.u.bits.FunctionNumber = k;
-
-            /* Read the vendor for this slot */
-            PciReadSlotConfig(DeviceExtension,
-                              PciSlot,
-                              PciData,
-                              0,
-                              sizeof(USHORT));
-
-            /* Skip invalid device */
-            if (PciData->VendorID == PCI_INVALID_VENDORID) continue;
-
-            /* Now read the whole header */
-            PciReadSlotConfig(DeviceExtension,
-                              PciSlot,
-                              &PciData->DeviceID,
-                              sizeof(USHORT),
-                              PCI_COMMON_HDR_LENGTH - sizeof(USHORT));
-
-            /* Apply any hacks before even analyzing the configuration header */
-            PciApplyHacks(DeviceExtension,
-                          PciData,
-                          PciSlot,
-                          PCI_HACK_FIXUP_BEFORE_CONFIGURATION,
-                          NULL);
-
-            /* Dump device that was found */
-            DPRINT1("Scan Found Device 0x%x (b=0x%x, d=0x%x, f=0x%x)\n",
-                    PciSlot.u.AsULONG,
-                    i,
-                    j,
-                    k);
-
-            /* Dump the device's header */
-            PciDebugDumpCommonConfig(PciData);
-
-            /* Find description for this device for the debugger's sake */
-            DescriptionText = PciGetDeviceDescriptionMessage(PciData->BaseClass,
-                                                             PciData->SubClass);
-            DPRINT1("Device Description \"%S\".\n",
-                    DescriptionText ? DescriptionText : L"(NULL)");
-            if (DescriptionText) ExFreePoolWithTag(DescriptionText, 0);
-
-            /* Check if there is an ACPI Watchdog Table */
-            if (WdTable)
-            {
-                /* Check if this PCI device is the ACPI Watchdog Device... */
-                UNIMPLEMENTED;
-                while (TRUE);
-            }
-
-            /* Check for non-simple devices */
-            if ((PCI_MULTIFUNCTION_DEVICE(PciData)) ||
-                (PciData->BaseClass == PCI_CLASS_BRIDGE_DEV))
-            {
-                /* No subsystem data defined for these kinds of bridges */
-                SubVendorId = 0;
-                SubSystemId = 0;
-            }
-            else
-            {
-                /* Read the subsystem information from the PCI header */
-                SubVendorId = PciData->u.type0.SubVendorID;
-                SubSystemId = PciData->u.type0.SubSystemID;
-            }
-
-            /* Get any hack flags for this device */
-            HackFlags = PciGetHackFlags(PciData->VendorID,
-                                        PciData->DeviceID,
-                                        SubVendorId,
-                                        SubSystemId,
-                                        PciData->RevisionID);
-
-            /* Check if this device is considered critical by the OS */
-            if (PciIsCriticalDeviceClass(PciData->BaseClass, PciData->SubClass))
-            {
-                /* Check if normally the decodes would be disabled */
-                if (!(HackFlags & PCI_HACK_DONT_DISABLE_DECODES))
-                {
-                    /* Because this device is critical, don't disable them */
-                    DPRINT1("Not allowing PM Because device is critical\n");
-                    HackFlags |= PCI_HACK_CRITICAL_DEVICE;
-                }
-            }
-
-            /* PCI bridges with a VGA card are also considered critical */
-            if ((PciData->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
-                (PciData->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI) &&
-                (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA) &&
-               !(HackFlags & PCI_HACK_DONT_DISABLE_DECODES))
-            {
-                /* Do not disable their decodes either */
-                DPRINT1("Not allowing PM because device is VGA\n");
-                HackFlags |= PCI_HACK_CRITICAL_DEVICE;
-            }
-
-            /* Check if the device should be skipped for whatever reason */
-            if (PciSkipThisFunction(PciData,
-                                    PciSlot,
-                                    PCI_SKIP_DEVICE_ENUMERATION,
-                                    HackFlags))
-            {
-                /* Skip this device */
-                continue;
-            }
-
-            /* Check if a PDO has already been created for this device */
-            PdoExtension = PciFindPdoByFunction(DeviceExtension,
-                                                PciSlot.u.AsULONG,
-                                                PciData);
-            if (PdoExtension)
-            {
-                /* Rescan scenarios are not yet implemented */
-                UNIMPLEMENTED;
-                while (TRUE);
-            }
-
-            /* Bus processing will need to happen */
-            ProcessFlag = TRUE;
-
-            /* Create the PDO for this device */
-            Status = PciPdoCreate(DeviceExtension, PciSlot, &DeviceObject);
-            ASSERT(NT_SUCCESS(Status));
-            NewExtension = (PPCI_PDO_EXTENSION)DeviceObject->DeviceExtension;
-
-            /* Check for broken devices with wrong/no class codes */
-            if (HackFlags & PCI_HACK_FAKE_CLASS_CODE)
-            {
-                /* Setup a default one */
-                PciData->BaseClass = PCI_CLASS_BASE_SYSTEM_DEV;
-                PciData->SubClass = PCI_SUBCLASS_SYS_OTHER;
-
-                /* Device will behave erratically when reading back data */
-                NewExtension->ExpectedWritebackFailure = TRUE;
-            }
-
-            /* Clone all the information from the header */
-            NewExtension->VendorId = PciData->VendorID;
-            NewExtension->DeviceId = PciData->DeviceID;
-            NewExtension->RevisionId = PciData->RevisionID;
-            NewExtension->ProgIf = PciData->ProgIf;
-            NewExtension->SubClass = PciData->SubClass;
-            NewExtension->BaseClass = PciData->BaseClass;
-            NewExtension->HeaderType = PCI_CONFIGURATION_TYPE(PciData);
-
-            /* Check for modern bridge types, which are managed by the driver */
-            if ((NewExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
-                ((NewExtension->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI) ||
-                 (NewExtension->SubClass == PCI_SUBCLASS_BR_CARDBUS)))
-            {
-                /* Acquire this device's lock */
-                KeEnterCriticalRegion();
-                KeWaitForSingleObject(&DeviceExtension->ChildListLock,
-                                      Executive,
-                                      KernelMode,
-                                      FALSE,
-                                      NULL);
-
-                /* Scan the bridge list until the first free entry */
-                for (BridgeExtension = &DeviceExtension->ChildBridgePdoList;
-                     *BridgeExtension;
-                     BridgeExtension = &(*BridgeExtension)->NextBridge);
-
-                /* Add this PDO as a bridge */
-                *BridgeExtension = NewExtension;
-                ASSERT(NewExtension->NextBridge == NULL);
-
-                /* Release this device's lock */
-                KeSetEvent(&DeviceExtension->ChildListLock,
-                           IO_NO_INCREMENT,
-                           FALSE);
-                KeLeaveCriticalRegion();
-            }
-
-            /* Get the PCI BIOS configuration saved in the registry */
-            Status = PciGetBiosConfig(NewExtension, BiosData);
-            if (NT_SUCCESS(Status))
-            {
-                /* This path has not yet been fully tested by eVb */
-                DPRINT1("Have BIOS configuration!\n");
-                UNIMPLEMENTED;
-
-                /* Check if the PCI BIOS configuration has changed */
-                if (!PcipIsSameDevice(NewExtension, BiosData))
-                {
-                    /* This is considered failure, and new data will be saved */
-                    Status = STATUS_UNSUCCESSFUL;
-                }
-                else
-                {
-                    /* Data is still correct, check for interrupt line change */
-                    if (BiosData->u.type0.InterruptLine !=
-                        PciData->u.type0.InterruptLine)
-                    {
-                        /* Update the current BIOS with the saved interrupt line */
-                        PciWriteDeviceConfig(NewExtension,
-                                             &BiosData->u.type0.InterruptLine,
-                                             FIELD_OFFSET(PCI_COMMON_HEADER,
-                                                          u.type0.InterruptLine),
-                                             sizeof(UCHAR));
-                    }
-
-                    /* Save the BIOS interrupt line and the initial command */
-                    NewExtension->RawInterruptLine = BiosData->u.type0.InterruptLine;
-                    NewExtension->InitialCommand = BiosData->Command;
-                }
-            }
-
-            /* Check if no saved data was present or if it was a mismatch */
-            if (!NT_SUCCESS(Status))
-            {
-                /* Save the new data */
-                Status = PciSaveBiosConfig(NewExtension, PciData);
-                ASSERT(NT_SUCCESS(Status));
-
-                /* Save the interrupt line and command from the device */
-                NewExtension->RawInterruptLine = PciData->u.type0.InterruptLine;
-                NewExtension->InitialCommand = PciData->Command;
-            }
-
-            /* Save original command from the device and hack flags */
-            NewExtension->CommandEnables = PciData->Command;
-            NewExtension->HackFlags = HackFlags;
-
-            /* Get power, AGP, and other capability data */
-            PciGetEnhancedCapabilities(NewExtension, PciData);
-
-            /* Now configure the BARs */
-            Status = PciGetFunctionLimits(NewExtension, PciData, HackFlags);
-
-            /* Power up the device */
-            PciSetPowerManagedDevicePowerState(NewExtension, PowerDeviceD0, FALSE);
-
-            /* Apply any device hacks required for enumeration */
-            PciApplyHacks(DeviceExtension,
-                          PciData,
-                          PciSlot,
-                          PCI_HACK_FIXUP_AFTER_CONFIGURATION,
-                          NewExtension);
-
-            /* Save interrupt pin */
-            NewExtension->InterruptPin = PciData->u.type0.InterruptPin;
-
-            /*
-             * Use either this device's actual IRQ line or, if it's connected on
-             * a master bus whose IRQ line is actually connected to the host, use
-             * the HAL to query the bus' IRQ line and store that as the adjusted
-             * interrupt line instead
-             */
-            NewExtension->AdjustedInterruptLine = PciGetAdjustedInterruptLine(NewExtension);
-
-            /* Check if this device is used for PCI debugger cards */
-            NewExtension->OnDebugPath = PciIsDeviceOnDebugPath(NewExtension);
-
-            /* Check for devices with invalid/bogus subsystem data */
-            if (HackFlags & PCI_HACK_NO_SUBSYSTEM)
-            {
-                /* Set the subsystem information to zero instead */
-                NewExtension->SubsystemVendorId = 0;
-                NewExtension->SubsystemId = 0;
-            }
-
-            /* Scan all capabilities */
-            CapOffset = NewExtension->CapabilitiesPtr;
-            while (CapOffset)
-            {
-                /* Read this header */
-                TempOffset = PciReadDeviceCapability(NewExtension,
-                                                     CapOffset,
-                                                     0,
-                                                     &CapHeader,
-                                                     sizeof(PCI_CAPABILITIES_HEADER));
-                if (TempOffset != CapOffset)
-                {
-                    /* This is a strange issue that shouldn't happen normally */
-                    DPRINT1("PCI - Failed to read PCI capability at offset 0x%02x\n",
-                            CapOffset);
-                    ASSERT(TempOffset == CapOffset);
-                }
-
-                /* Check for capabilities that this driver cares about */
-                switch (CapHeader.CapabilityID)
-                {
-                    /* Power management capability is heavily used by the bus */
-                    case PCI_CAPABILITY_ID_POWER_MANAGEMENT:
-
-                        /* Dump the capability */
-                        Name = "POWER";
-                        Size = sizeof(PCI_PM_CAPABILITY);
-                        break;
-
-                    /* AGP capability is required for AGP bus functionality */
-                    case PCI_CAPABILITY_ID_AGP:
-
-                        /* Dump the capability */
-                        Name = "AGP";
-                        Size = sizeof(PCI_AGP_CAPABILITY);
-                        break;
-
-                    /* This driver doesn't really use anything other than that */
-                    default:
-
-                        /* Windows prints this, we could do a translation later */
-                        Name = "UNKNOWN CAPABILITY";
-                        Size = 0;
-                        break;
-                }
-
-                /* Check if this is a capability that should be dumped */
-                if (Size)
-                {
-                    /* Read the whole capability data */
-                    TempOffset = PciReadDeviceCapability(NewExtension,
-                                                         CapOffset,
-                                                         CapHeader.CapabilityID,
-                                                         &CapHeader,
-                                                         Size);
-
-                    if (TempOffset != CapOffset)
-                    {
-                        /* Again, a strange issue that shouldn't be seen */
-                        DPRINT1("- Failed to read capability data. ***\n");
-                        ASSERT(TempOffset == CapOffset);
-                    }
-                }
-
-                /* Dump this capability */
-                DPRINT1("CAP @%02x ID %02x (%s)\n",
-                        CapOffset, CapHeader.CapabilityID, Name);
-                for (i = 0; i < Size; i += 2)
-                    DPRINT1("  %04x\n", *(PUSHORT)((ULONG_PTR)&CapHeader + i));
-                DPRINT1("\n");
-
-                /* Check the next capability */
-                CapOffset = CapHeader.Next;
-            }
-
-            /* Check for IDE controllers */
-            if ((NewExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
-                (NewExtension->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
-            {
-                /* Do not allow them to power down completely */
-                NewExtension->DisablePowerDown = TRUE;
-            }
-
-            /*
-             * Check if this is a legacy bridge. Note that the i82375 PCI/EISA
-             * bridge that is present on certain NT Alpha machines appears as
-             * non-classified so detect it manually by scanning for its VID/PID.
-             */
-            if (((NewExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
-                ((NewExtension->SubClass == PCI_SUBCLASS_BR_ISA) ||
-                 (NewExtension->SubClass == PCI_SUBCLASS_BR_EISA) ||
-                 (NewExtension->SubClass == PCI_SUBCLASS_BR_MCA))) ||
-                ((NewExtension->VendorId == 0x8086) &&
-                 (NewExtension->DeviceId == 0x482)))
-            {
-                /* Do not allow these legacy bridges to be powered down */
-                NewExtension->DisablePowerDown = TRUE;
-            }
-
-            /* Check if the BIOS did not configure a cache line size */
-            if (!PciData->CacheLineSize)
-            {
-                /* Check if the device is disabled */
-                if (!(NewExtension->CommandEnables & (PCI_ENABLE_IO_SPACE |
-                                                      PCI_ENABLE_MEMORY_SPACE |
-                                                      PCI_ENABLE_BUS_MASTER)))
-                {
-                    /* Check if this is a PCI-X device*/
-                    TempOffset = PciReadDeviceCapability(NewExtension,
-                                                         NewExtension->CapabilitiesPtr,
-                                                         PCI_CAPABILITY_ID_PCIX,
-                                                         &PcixCapHeader,
-                                                         sizeof(PCI_CAPABILITIES_HEADER));
-
-                    /*
-                     * A device with default cache line size and latency timer
-                     * settings is considered to be unconfigured. Note that on
-                     * PCI-X, the reset value of the latency timer field in the
-                     * header is 64, not 0, hence why the check for PCI-X caps
-                     * was required, and the value used here below.
-                     */
-                    if (!(PciData->LatencyTimer) ||
-                        ((TempOffset) && (PciData->LatencyTimer == 64)))
-                    {
-                        /* Keep track of the fact that it needs configuration */
-                        DPRINT1("PCI - ScanBus, PDOx %x found unconfigured\n",
-                                NewExtension);
-                        NewExtension->NeedsHotPlugConfiguration = TRUE;
-                    }
-                }
-            }
-
-            /* Save latency and cache size information */
-            NewExtension->SavedLatencyTimer = PciData->LatencyTimer;
-            NewExtension->SavedCacheLineSize = PciData->CacheLineSize;
-
-            /* The PDO is now ready to go */
-            DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
-        }
-    }
-
-    /* Enumeration completed, do a final pass now that all devices are found */
-    if (ProcessFlag) PciProcessBus(DeviceExtension);
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-PciQueryDeviceRelations(IN PPCI_FDO_EXTENSION DeviceExtension,
-                        IN OUT PDEVICE_RELATIONS *pDeviceRelations)
-{
-    NTSTATUS Status;
-    PPCI_PDO_EXTENSION PdoExtension;
-    ULONG PdoCount = 0;
-    PDEVICE_RELATIONS DeviceRelations, NewRelations;
-    SIZE_T Size;
-    PDEVICE_OBJECT DeviceObject, *ObjectArray;
-    PAGED_CODE();
-
-    /* Make sure the FDO is started */
-    ASSERT(DeviceExtension->DeviceState == PciStarted);
-
-    /* Synchronize while we enumerate the bus */
-    Status = PciBeginStateTransition(DeviceExtension, PciSynchronizedOperation);
-    if (!NT_SUCCESS(Status)) return Status;
-
-    /* Scan all children PDO */
-    for (PdoExtension = DeviceExtension->ChildPdoList;
-         PdoExtension;
-         PdoExtension = PdoExtension->Next)
-    {
-        /* Invalidate them */
-        PdoExtension->NotPresent = TRUE;
-    }
-
-    /* Scan the PCI Bus */
-    Status = PciScanBus(DeviceExtension);
-    ASSERT(NT_SUCCESS(Status));
-
-    /* Enumerate all children PDO again */
-    for (PdoExtension = DeviceExtension->ChildPdoList;
-         PdoExtension;
-         PdoExtension = PdoExtension->Next)
-    {
-        /* Check for PDOs that are still invalidated */
-        if (PdoExtension->NotPresent)
-        {
-            /* This means this PDO existed before, but not anymore */
-            PdoExtension->ReportedMissing = TRUE;
-            DPRINT1("PCI - Old device (pdox) %08x not found on rescan.\n",
-                    PdoExtension);
-        }
-        else
-        {
-            /* Increase count of detected PDOs */
-            PdoCount++;
-        }
-    }
-
-    /* Read the current relations and add the newly discovered relations */
-    DeviceRelations = *pDeviceRelations;
-    Size = FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
-           PdoCount * sizeof(PDEVICE_OBJECT);
-    if (DeviceRelations) Size += sizeof(PDEVICE_OBJECT) * DeviceRelations->Count;
-
-    /* Allocate the device relations */
-    NewRelations = (PDEVICE_RELATIONS)ExAllocatePoolWithTag(0, Size, 'BicP');
-    if (!NewRelations)
-    {
-        /* Out of space, cancel the operation */
-        PciCancelStateTransition(DeviceExtension, PciSynchronizedOperation);
-        return STATUS_INSUFFICIENT_RESOURCES;
-    }
-
-    /* Check if there were any older relations */
-    NewRelations->Count = 0;
-    if (DeviceRelations)
-    {
-        /* Copy the old relations into the new buffer, then free the old one */
-        RtlCopyMemory(NewRelations,
-                      DeviceRelations,
-                      FIELD_OFFSET(DEVICE_RELATIONS, Objects) +
-                      DeviceRelations->Count * sizeof(PDEVICE_OBJECT));
-        ExFreePoolWithTag(DeviceRelations, 0);
-    }
-
-    /* Print out that we're ready to dump relations */
-    DPRINT1("PCI QueryDeviceRelations/BusRelations FDOx %08x (bus 0x%02x)\n",
-            DeviceExtension,
-            DeviceExtension->BaseBus);
-
-    /* Loop the current PDO children and the device relation object array */
-    PdoExtension = DeviceExtension->ChildPdoList;
-    ObjectArray = &NewRelations->Objects[NewRelations->Count];
-    while (PdoExtension)
-    {
-        /* Dump this relation */
-        DPRINT1("  QDR PDO %08x (x %08x)%s\n",
-                PdoExtension->PhysicalDeviceObject,
-                PdoExtension,
-                PdoExtension->NotPresent ?
-                "<Omitted, device flaged not present>" : "");
-
-        /* Is this PDO present? */
-        if (!PdoExtension->NotPresent)
-        {
-            /* Reference it and add it to the array */
-            DeviceObject = PdoExtension->PhysicalDeviceObject;
-            ObfReferenceObject(DeviceObject);
-            *ObjectArray++ = DeviceObject;
-        }
-
-        /* Go to the next PDO */
-        PdoExtension = PdoExtension->Next;
-    }
-
-    /* Terminate dumping the relations */
-    DPRINT1("  QDR Total PDO count = %d (%d already in list)\n",
-            NewRelations->Count + PdoCount,
-            NewRelations->Count);
-
-    /* Return the final count and the new buffer */
-    NewRelations->Count += PdoCount;
-    *pDeviceRelations = NewRelations;
-    return STATUS_SUCCESS;
-}
-
-NTSTATUS
-NTAPI
-PciSetResources(IN PPCI_PDO_EXTENSION PdoExtension,
-                IN BOOLEAN DoReset,
-                IN BOOLEAN SomethingSomethingDarkSide)
-{
-    PPCI_FDO_EXTENSION FdoExtension;
-    UCHAR NewCacheLineSize, NewLatencyTimer;
-    PCI_COMMON_HEADER PciData;
-    BOOLEAN Native;
-    PPCI_CONFIGURATOR Configurator;
-
-    /* Get the FDO and read the configuration data */
-    FdoExtension = PdoExtension->ParentFdoExtension;
-    PciReadDeviceConfig(PdoExtension, &PciData, 0, PCI_COMMON_HDR_LENGTH);
-
-    /* Make sure this is still the same device */
-    if (!PcipIsSameDevice(PdoExtension, &PciData))
-    {
-        /* Fail */
-        ASSERTMSG(FALSE, "PCI Set resources - not same device");
-        return STATUS_DEVICE_DOES_NOT_EXIST;
-    }
-
-    /* Nothing to set for a host bridge */
-    if ((PdoExtension->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
-        (PdoExtension->SubClass == PCI_SUBCLASS_BR_HOST))
-    {
-        /* Fake success */
-        return STATUS_SUCCESS;
-    }
-
-    /* Check if an IDE controller is being reset */
-    if ((DoReset) &&
-        (PdoExtension->BaseClass == PCI_CLASS_MASS_STORAGE_CTLR) &&
-        (PdoExtension->SubClass == PCI_SUBCLASS_MSC_IDE_CTLR))
-    {
-        /* Turn off native mode */
-        Native = PciConfigureIdeController(PdoExtension, &PciData, FALSE);
-        ASSERT(Native == PdoExtension->IDEInNativeMode);
-    }
-
-    /* Check for update of a hotplug device, or first configuration of one */
-    if ((PdoExtension->NeedsHotPlugConfiguration) &&
-        (FdoExtension->HotPlugParameters.Acquired))
-    {
-        /* Don't have hotplug devices to test with yet, QEMU 0.14 should */
-        UNIMPLEMENTED;
-        while (TRUE);
-    }
-
-    /* Locate the correct resource configurator for this type of device */
-    Configurator = &PciConfigurators[PdoExtension->HeaderType];
-
-    /* Apply the settings change */
-    Configurator->ChangeResourceSettings(PdoExtension, &PciData);
-
-    /* Assume no update needed */
-    PdoExtension->UpdateHardware = FALSE;
-
-    /* Check if a reset is needed */
-    if (DoReset)
-    {
-        /* Reset resources */
-        Configurator->ResetDevice(PdoExtension, &PciData);
-        PciData.u.type0.InterruptLine = PdoExtension->RawInterruptLine;
-    }
-
-    /* Check if the latency timer changed */
-    NewLatencyTimer = PdoExtension->SavedLatencyTimer;
-    if (PciData.LatencyTimer != NewLatencyTimer)
-    {
-        /* Debug notification */
-        DPRINT1("PCI (pdox %08x) changing latency from %02x to %02x.\n",
-                PdoExtension,
-                PciData.LatencyTimer,
-                NewLatencyTimer);
-    }
-
-    /* Check if the cache line changed */
-    NewCacheLineSize = PdoExtension->SavedCacheLineSize;
-    if (PciData.CacheLineSize != NewCacheLineSize)
-    {
-        /* Debug notification */
-        DPRINT1("PCI (pdox %08x) changing cache line size from %02x to %02x.\n",
-                PdoExtension,
-                PciData.CacheLineSize,
-                NewCacheLineSize);
-    }
-
-    /* Inherit data from PDO extension */
-    PciData.LatencyTimer = PdoExtension->SavedLatencyTimer;
-    PciData.CacheLineSize = PdoExtension->SavedCacheLineSize;
-    PciData.u.type0.InterruptLine = PdoExtension->RawInterruptLine;
-
-    /* Apply any resource hacks required */
-    PciApplyHacks(FdoExtension,
-                  &PciData,
-                  PdoExtension->Slot,
-                  PCI_HACK_FIXUP_BEFORE_UPDATE,
-                  PdoExtension);
-
-    /* Check if I/O space was disabled by administrator or driver */
-    if (PdoExtension->IoSpaceNotRequired)
-    {
-        /* Don't turn on the decode */
-        PdoExtension->CommandEnables &= ~PCI_ENABLE_IO_SPACE;
-    }
-
-    /* Update the device with the new settings */
-    PciUpdateHardware(PdoExtension, &PciData);
-
-    /* Update complete */
-    PdoExtension->RawInterruptLine = PciData.u.type0.InterruptLine;
-    PdoExtension->NeedsHotPlugConfiguration = FALSE;
-    return STATUS_SUCCESS;
-}
-
-/* EOF */