Implement stubs for PCI_DEVICE_PRESENT_INTERFACE query-interface, plus fixes from...
[reactos.git] / reactos / drivers / bus / pci / pdo.c
index a1454e3..700b351 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id: pdo.c,v 1.5 2004/06/09 14:22:53 ekohl Exp $
- *
+/*
  * PROJECT:         ReactOS PCI bus driver
  * FILE:            pdo.c
  * PURPOSE:         Child device object dispatch routines
@@ -9,18 +8,54 @@
  */
 
 #include <ddk/ntddk.h>
-
+#include <ddk/ntifs.h>
+#include <initguid.h>
+#include <ddk/wdmguid.h>
 #include "pcidef.h"
 #include "pci.h"
 
 #define NDEBUG
 #include <debug.h>
 
-DEFINE_GUID(GUID_BUS_TYPE_PCI, 0xc8ebdfb0L, 0xb510, 0x11d0, 0x80, 0xe5, 0x00, 0xa0, 0xc9, 0x25, 0x42, 0xe3);
-
 /*** PRIVATE *****************************************************************/
 
-NTSTATUS
+static NTSTATUS
+PdoQueryDeviceText(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  NTSTATUS Status;
+
+  DPRINT("Called\n");
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  Status = STATUS_SUCCESS;
+
+  switch (IrpSp->Parameters.QueryDeviceText.DeviceTextType)
+  {
+    case DeviceTextDescription:
+      DPRINT("DeviceTextDescription\n");
+      Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceDescription.Buffer;
+      break;
+
+    case DeviceTextLocationInformation:
+      DPRINT("DeviceTextLocationInformation\n");
+      Irp->IoStatus.Information = (ULONG_PTR)DeviceExtension->DeviceLocation.Buffer;
+      break;
+
+    default:
+      Irp->IoStatus.Information = 0;
+      Status = STATUS_INVALID_PARAMETER;
+  }
+
+  return Status;
+}
+
+
+static NTSTATUS
 PdoQueryId(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp,
@@ -42,10 +77,10 @@ PdoQueryId(
 
   switch (IrpSp->Parameters.QueryId.IdType) {
     case BusQueryDeviceID:
-      Status = PciDuplicateUnicodeString(
-        &String,
+      Status = RtlDuplicateUnicodeString(
+        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
         &DeviceExtension->DeviceID,
-        PagedPool);
+        &String);
 
       DPRINT("DeviceID: %S\n", String.Buffer);
 
@@ -53,28 +88,28 @@ PdoQueryId(
       break;
 
     case BusQueryHardwareIDs:
-      Status = PciDuplicateUnicodeString(
-        &String,
+      Status = RtlDuplicateUnicodeString(
+        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
         &DeviceExtension->HardwareIDs,
-        PagedPool);
+        &String);
 
       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
       break;
 
     case BusQueryCompatibleIDs:
-      Status = PciDuplicateUnicodeString(
-        &String,
+      Status = RtlDuplicateUnicodeString(
+        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
         &DeviceExtension->CompatibleIDs,
-        PagedPool);
+        &String);
 
       Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
       break;
 
     case BusQueryInstanceID:
-      Status = PciDuplicateUnicodeString(
-        &String,
+      Status = RtlDuplicateUnicodeString(
+        RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
         &DeviceExtension->InstanceID,
-        PagedPool);
+        &String);
 
       DPRINT("InstanceID: %S\n", String.Buffer);
 
@@ -90,7 +125,7 @@ PdoQueryId(
 }
 
 
-NTSTATUS
+static NTSTATUS
 PdoQueryBusInformation(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp,
@@ -110,7 +145,7 @@ PdoQueryBusInformation(
   {
     BusInformation->BusTypeGuid = GUID_BUS_TYPE_PCI;
     BusInformation->LegacyBusType = PCIBus;
-    BusInformation->BusNumber = DeviceExtension->BusNumber;
+    BusInformation->BusNumber = DeviceExtension->PciDevice->BusNumber;
 
     return STATUS_SUCCESS;
   }
@@ -119,7 +154,7 @@ PdoQueryBusInformation(
 }
 
 
-NTSTATUS
+static NTSTATUS
 PdoQueryCapabilities(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp,
@@ -133,14 +168,964 @@ PdoQueryCapabilities(
   DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
   DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;
 
-  DeviceCapabilities->Address =
-  DeviceCapabilities->UINumber = DeviceExtension->SlotNumber.u.AsULONG;
+  if (DeviceCapabilities->Version != 1)
+    return STATUS_UNSUCCESSFUL;
+
+  DeviceCapabilities->UniqueID = FALSE;
+  DeviceCapabilities->Address = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
+  DeviceCapabilities->UINumber = (ULONG)-1; /* FIXME */
 
   return STATUS_SUCCESS;
 }
 
 
-NTSTATUS
+static BOOLEAN
+PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
+                  ULONG Offset,
+                  PULONG Base,
+                  PULONG Length,
+                  PULONG Flags)
+{
+  ULONG OrigValue;
+  ULONG BaseValue;
+  ULONG NewValue;
+  ULONG Size;
+  ULONG XLength;
+
+  /* Save original value */
+  Size= HalGetBusDataByOffset(PCIConfiguration,
+                              DeviceExtension->PciDevice->BusNumber,
+                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                              &OrigValue,
+                              Offset,
+                              sizeof(ULONG));
+  if (Size != sizeof(ULONG))
+  {
+    DPRINT1("Wrong size %lu\n", Size);
+    return FALSE;
+  }
+
+  BaseValue = (OrigValue & 0x00000001) ? (OrigValue & ~0x3) : (OrigValue & ~0xF);
+
+  *Base = BaseValue;
+
+  /* Set magic value */
+  NewValue = (ULONG)-1;
+  Size= HalSetBusDataByOffset(PCIConfiguration,
+                              DeviceExtension->PciDevice->BusNumber,
+                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                              &NewValue,
+                              Offset,
+                              sizeof(ULONG));
+  if (Size != sizeof(ULONG))
+  {
+    DPRINT1("Wrong size %lu\n", Size);
+    return FALSE;
+  }
+
+  /* Get the range length */
+  Size= HalGetBusDataByOffset(PCIConfiguration,
+                              DeviceExtension->PciDevice->BusNumber,
+                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                              &NewValue,
+                              Offset,
+                              sizeof(ULONG));
+  if (Size != sizeof(ULONG))
+  {
+    DPRINT1("Wrong size %lu\n", Size);
+    return FALSE;
+  }
+
+  /* Restore original value */
+  Size= HalSetBusDataByOffset(PCIConfiguration,
+                              DeviceExtension->PciDevice->BusNumber,
+                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                              &OrigValue,
+                              Offset,
+                              sizeof(ULONG));
+  if (Size != sizeof(ULONG))
+  {
+    DPRINT1("Wrong size %lu\n", Size);
+    return FALSE;
+  }
+
+  if (NewValue == 0)
+  {
+    DPRINT("Unused address register\n");
+    *Base = 0;
+    *Length = 0;
+    *Flags = 0;
+     return TRUE;
+  }
+
+  XLength = ~((NewValue & 0x00000001) ? (NewValue & ~0x3) : (NewValue & ~0xF)) + 1;
+
+#if 0
+  DbgPrint("BaseAddress 0x%08lx  Length 0x%08lx",
+           BaseValue, XLength);
+
+  if (NewValue & 0x00000001)
+  {
+    DbgPrint("  IO range");
+  }
+  else
+  {
+    DbgPrint("  Memory range");
+    if ((NewValue & 0x00000006) == 0)
+    {
+      DbgPrint(" in 32-Bit address space");
+    }
+    else if ((NewValue & 0x00000006) == 2)
+    {
+      DbgPrint(" below 1BM ");
+    }
+    else if ((NewValue & 0x00000006) == 4)
+    {
+      DbgPrint(" in 64-Bit address space");
+    }
+
+    if (NewValue & 0x00000008)
+    {
+      DbgPrint(" prefetchable");
+    }
+  }
+
+  DbgPrint("\n");
+#endif
+
+  *Length = XLength;
+  *Flags = (NewValue & 0x00000001) ? (NewValue & 0x3) : (NewValue & 0xF);
+
+  return TRUE;
+}
+
+
+static NTSTATUS
+PdoQueryResourceRequirements(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  PCI_COMMON_CONFIG PciConfig;
+  PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+  PIO_RESOURCE_DESCRIPTOR Descriptor;
+  ULONG Size;
+  ULONG ResCount = 0;
+  ULONG ListSize;
+  ULONG i;
+  ULONG Base;
+  ULONG Length;
+  ULONG Flags;
+
+  DPRINT("PdoQueryResourceRequirements() called\n");
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  /* Get PCI configuration space */
+  Size= HalGetBusData(PCIConfiguration,
+                      DeviceExtension->PciDevice->BusNumber,
+                      DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                      &PciConfig,
+                      PCI_COMMON_HDR_LENGTH);
+  DPRINT("Size %lu\n", Size);
+  if (Size < PCI_COMMON_HDR_LENGTH)
+  {
+    Irp->IoStatus.Information = 0;
+    return STATUS_UNSUCCESSFUL;
+  }
+
+  DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
+
+  /* Count required resource descriptors */
+  ResCount = 0;
+  if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+       break;
+
+      if (Length != 0)
+        ResCount += 2;
+    }
+
+    /* FIXME: Check ROM address */
+
+    if (PciConfig.u.type0.InterruptPin != 0)
+      ResCount++;
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+       break;
+
+      if (Length != 0)
+        ResCount += 2;
+    }
+    if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
+      ResCount++;
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
+  {
+  }
+  else
+  {
+    DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
+  }
+
+  if (ResCount == 0)
+  {
+    Irp->IoStatus.Information = 0;
+    return STATUS_SUCCESS;
+  }
+
+  /* Calculate the resource list size */
+  ListSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
+  if (ResCount > 1)
+  {
+    ListSize += ((ResCount - 1) * sizeof(IO_RESOURCE_DESCRIPTOR));
+  }
+
+  DPRINT("ListSize %lu (0x%lx)\n", ListSize, ListSize);
+
+  /* Allocate the resource requirements list */
+  ResourceList = ExAllocatePool(PagedPool,
+                                ListSize);
+  if (ResourceList == NULL)
+  {
+    Irp->IoStatus.Information = 0;
+    return STATUS_INSUFFICIENT_RESOURCES;
+  }
+
+  ResourceList->ListSize = ListSize;
+  ResourceList->InterfaceType = PCIBus;
+  ResourceList->BusNumber = DeviceExtension->PciDevice->BusNumber;
+  ResourceList->SlotNumber = DeviceExtension->PciDevice->SlotNumber.u.AsULONG;
+  ResourceList->AlternativeLists = 1;
+
+  ResourceList->List[0].Version = 1;
+  ResourceList->List[0].Revision = 1;
+  ResourceList->List[0].Count = ResCount;
+
+  Descriptor = &ResourceList->List[0].Descriptors[0];
+  if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+      {
+        DPRINT1("PdoGetRangeLength() failed\n");
+        break;
+      }
+
+      if (Length == 0)
+      {
+        DPRINT("Unused address register\n");
+        continue;
+      }
+
+      /* Set preferred descriptor */
+      Descriptor->Option = IO_RESOURCE_PREFERRED;
+      if (Flags & PCI_ADDRESS_IO_SPACE)
+      {
+        Descriptor->Type = CmResourceTypePort;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_PORT_IO |
+                            CM_RESOURCE_PORT_16_BIT_DECODE |
+                            CM_RESOURCE_PORT_POSITIVE_DECODE;
+
+        Descriptor->u.Port.Length = Length;
+        Descriptor->u.Port.Alignment = 1;
+        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
+        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
+      }
+      else
+      {
+        Descriptor->Type = CmResourceTypeMemory;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+
+        Descriptor->u.Memory.Length = Length;
+        Descriptor->u.Memory.Alignment = 1;
+        Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
+        Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
+      }
+      Descriptor++;
+
+      /* Set alternative descriptor */
+      Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+      if (Flags & PCI_ADDRESS_IO_SPACE)
+      {
+        Descriptor->Type = CmResourceTypePort;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_PORT_IO |
+                            CM_RESOURCE_PORT_16_BIT_DECODE |
+                            CM_RESOURCE_PORT_POSITIVE_DECODE;
+
+        Descriptor->u.Port.Length = Length;
+        Descriptor->u.Port.Alignment = Length;
+        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
+        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
+      }
+      else
+      {
+        Descriptor->Type = CmResourceTypeMemory;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+
+        Descriptor->u.Memory.Length = Length;
+        Descriptor->u.Memory.Alignment = Length;
+        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
+        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
+      }
+      Descriptor++;
+    }
+
+    /* FIXME: Check ROM address */
+
+    if (PciConfig.u.type0.InterruptPin != 0)
+    {
+      Descriptor->Option = 0; /* Required */
+      Descriptor->Type = CmResourceTypeInterrupt;
+      Descriptor->ShareDisposition = CmResourceShareShared;
+      Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+      Descriptor->u.Interrupt.MinimumVector = 0;
+      Descriptor->u.Interrupt.MaximumVector = 0xFF;
+    }
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+      {
+        DPRINT1("PdoGetRangeLength() failed\n");
+        break;
+      }
+
+      if (Length == 0)
+      {
+        DPRINT("Unused address register\n");
+        continue;
+      }
+
+      /* Set preferred descriptor */
+      Descriptor->Option = IO_RESOURCE_PREFERRED;
+      if (Flags & PCI_ADDRESS_IO_SPACE)
+      {
+        Descriptor->Type = CmResourceTypePort;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_PORT_IO |
+                            CM_RESOURCE_PORT_16_BIT_DECODE |
+                            CM_RESOURCE_PORT_POSITIVE_DECODE;
+
+        Descriptor->u.Port.Length = Length;
+        Descriptor->u.Port.Alignment = 1;
+        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)Base;
+        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
+      }
+      else
+      {
+        Descriptor->Type = CmResourceTypeMemory;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+
+        Descriptor->u.Memory.Length = Length;
+        Descriptor->u.Memory.Alignment = 1;
+        Descriptor->u.Memory.MinimumAddress.QuadPart = (ULONGLONG)Base;
+        Descriptor->u.Memory.MaximumAddress.QuadPart = (ULONGLONG)(Base + Length - 1);
+      }
+      Descriptor++;
+
+      /* Set alternative descriptor */
+      Descriptor->Option = IO_RESOURCE_ALTERNATIVE;
+      if (Flags & PCI_ADDRESS_IO_SPACE)
+      {
+        Descriptor->Type = CmResourceTypePort;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_PORT_IO |
+                            CM_RESOURCE_PORT_16_BIT_DECODE |
+                            CM_RESOURCE_PORT_POSITIVE_DECODE;
+
+        Descriptor->u.Port.Length = Length;
+        Descriptor->u.Port.Alignment = Length;
+        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
+        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
+      }
+      else
+      {
+        Descriptor->Type = CmResourceTypeMemory;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+
+        Descriptor->u.Memory.Length = Length;
+        Descriptor->u.Memory.Alignment = Length;
+        Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
+        Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
+      }
+      Descriptor++;
+    }
+    if (DeviceExtension->PciDevice->PciConfig.BaseClass == PCI_CLASS_BRIDGE_DEV)
+    {
+      Descriptor->Option = 0; /* Required */
+      Descriptor->Type = CmResourceTypeBusNumber;
+      Descriptor->ShareDisposition = CmResourceShareShared;
+      Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+
+      Descriptor->u.BusNumber.MinBusNumber =
+      Descriptor->u.BusNumber.MaxBusNumber = DeviceExtension->PciDevice->PciConfig.u.type1.SubordinateBus;
+      Descriptor->u.BusNumber.Length = 1;
+      Descriptor->u.BusNumber.Reserved = 0;
+    }
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
+  {
+    /* FIXME: Add Cardbus bridge resources */
+  }
+
+  Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+PdoQueryResources(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  PCI_COMMON_CONFIG PciConfig;
+  PCM_RESOURCE_LIST ResourceList;
+  PCM_PARTIAL_RESOURCE_LIST PartialList;
+  PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+  ULONG Size;
+  ULONG ResCount = 0;
+  ULONG ListSize;
+  ULONG i;
+  ULONG Base;
+  ULONG Length;
+  ULONG Flags;
+
+  DPRINT("PdoQueryResources() called\n");
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+  /* Get PCI configuration space */
+  Size= HalGetBusData(PCIConfiguration,
+                      DeviceExtension->PciDevice->BusNumber,
+                      DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                      &PciConfig,
+                      PCI_COMMON_HDR_LENGTH);
+  DPRINT("Size %lu\n", Size);
+  if (Size < PCI_COMMON_HDR_LENGTH)
+  {
+    Irp->IoStatus.Information = 0;
+    return STATUS_UNSUCCESSFUL;
+  }
+
+  DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
+
+  /* Count required resource descriptors */
+  ResCount = 0;
+  if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+        break;
+
+      if (Length)
+        ResCount++;
+    }
+
+    if ((PciConfig.u.type0.InterruptPin != 0) &&
+        (PciConfig.u.type0.InterruptLine != 0xFF))
+      ResCount++;
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+        break;
+
+      if (Length != 0)
+        ResCount++;
+    }
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
+  {
+
+  }
+  else
+  {
+    DPRINT1("Unsupported header type %u\n", PCI_CONFIGURATION_TYPE(&PciConfig));
+  }
+
+  if (ResCount == 0)
+  {
+    Irp->IoStatus.Information = 0;
+    return STATUS_SUCCESS;
+  }
+
+  /* Calculate the resource list size */
+  ListSize = sizeof(CM_RESOURCE_LIST);
+  if (ResCount > 1)
+  {
+    ListSize += ((ResCount - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
+  }
+
+  /* Allocate the resource list */
+  ResourceList = ExAllocatePool(PagedPool,
+                                ListSize);
+  if (ResourceList == NULL)
+    return STATUS_INSUFFICIENT_RESOURCES;
+
+  ResourceList->Count = 1;
+  ResourceList->List[0].InterfaceType = PCIConfiguration;
+  ResourceList->List[0].BusNumber = DeviceExtension->PciDevice->BusNumber;
+
+  PartialList = &ResourceList->List[0].PartialResourceList;
+  PartialList->Version = 0;
+  PartialList->Revision = 0;
+  PartialList->Count = ResCount;
+
+  Descriptor = &PartialList->PartialDescriptors[0];
+  if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+      {
+        DPRINT1("PdoGetRangeLength() failed\n");
+        break;
+      }
+
+      if (Length == 0)
+      {
+        DPRINT("Unused address register\n");
+        continue;
+      }
+
+      if (Flags & PCI_ADDRESS_IO_SPACE)
+      {
+        Descriptor->Type = CmResourceTypePort;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_PORT_IO;
+        Descriptor->u.Port.Start.QuadPart =
+          (ULONGLONG)Base;
+        Descriptor->u.Port.Length = Length;
+      }
+      else
+      {
+        Descriptor->Type = CmResourceTypeMemory;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+        Descriptor->u.Memory.Start.QuadPart =
+          (ULONGLONG)Base;
+        Descriptor->u.Memory.Length = Length;
+      }
+
+      Descriptor++;
+    }
+
+    /* Add interrupt resource */
+    if ((PciConfig.u.type0.InterruptPin != 0) &&
+        (PciConfig.u.type0.InterruptLine != 0xFF))
+    {
+      Descriptor->Type = CmResourceTypeInterrupt;
+      Descriptor->ShareDisposition = CmResourceShareShared;
+      Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+      Descriptor->u.Interrupt.Level = PciConfig.u.type0.InterruptLine;
+      Descriptor->u.Interrupt.Vector = PciConfig.u.type0.InterruptLine;
+      Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+    }
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
+  {
+    for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+    {
+      if (!PdoGetRangeLength(DeviceExtension,
+                            0x10 + i * 4,
+                            &Base,
+                            &Length,
+                            &Flags))
+      {
+        DPRINT1("PdoGetRangeLength() failed\n");
+        break;
+      }
+
+      if (Length == 0)
+      {
+        DPRINT("Unused address register\n");
+        continue;
+      }
+
+      if (Flags & PCI_ADDRESS_IO_SPACE)
+      {
+        Descriptor->Type = CmResourceTypePort;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_PORT_IO;
+        Descriptor->u.Port.Start.QuadPart =
+          (ULONGLONG)Base;
+        Descriptor->u.Port.Length = Length;
+      }
+      else
+      {
+        Descriptor->Type = CmResourceTypeMemory;
+        Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+        Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+        Descriptor->u.Memory.Start.QuadPart =
+          (ULONGLONG)Base;
+        Descriptor->u.Memory.Length = Length;
+      }
+
+      Descriptor++;
+    }
+  }
+  else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_CARDBUS_BRIDGE_TYPE)
+  {
+    /* FIXME: Cardbus */
+  }
+
+  Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+  return STATUS_SUCCESS;
+}
+
+
+static VOID NTAPI
+InterfaceReference(
+  IN PVOID Context)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+
+  DPRINT("InterfaceReference(%p)\n", Context);
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+  InterlockedIncrement(&DeviceExtension->References);
+}
+
+
+static VOID NTAPI
+InterfaceDereference(
+  IN PVOID Context)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+
+  DPRINT("InterfaceDereference(%p)\n", Context);
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+  InterlockedDecrement(&DeviceExtension->References);
+}
+
+
+static BOOLEAN NTAPI
+InterfaceBusTranslateBusAddress(
+  IN PVOID Context,
+  IN PHYSICAL_ADDRESS BusAddress,
+  IN ULONG Length,
+  IN OUT PULONG AddressSpace,
+  OUT PPHYSICAL_ADDRESS TranslatedAddress)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  PFDO_DEVICE_EXTENSION FdoDeviceExtension;
+
+  DPRINT("InterfaceBusTranslateBusAddress(%p %p 0x%lx %p %p)\n",
+    Context, BusAddress, Length, AddressSpace, TranslatedAddress);
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+  FdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;
+
+  return HalTranslateBusAddress(
+    PCIBus, FdoDeviceExtension->BusNumber,
+    BusAddress, AddressSpace, TranslatedAddress);
+}
+
+
+static PDMA_ADAPTER NTAPI
+InterfaceBusGetDmaAdapter(
+  IN PVOID Context,
+  IN PDEVICE_DESCRIPTION DeviceDescription,
+  OUT PULONG NumberOfMapRegisters)
+{
+  DPRINT("InterfaceBusGetDmaAdapter(%p %p %p)\n",
+    Context, DeviceDescription, NumberOfMapRegisters);
+  return (PDMA_ADAPTER)HalGetAdapter(DeviceDescription, NumberOfMapRegisters);
+}
+
+
+static ULONG NTAPI
+InterfaceBusSetBusData(
+  IN PVOID Context,
+  IN ULONG DataType,
+  IN PVOID Buffer,
+  IN ULONG Offset,
+  IN ULONG Length)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  ULONG Size;
+
+  DPRINT("InterfaceBusSetBusData(%p 0x%lx %p 0x%lx 0x%lx)\n",
+    Context, DataType, Buffer, Offset, Length);
+
+  if (DataType != PCI_WHICHSPACE_CONFIG)
+  {
+    DPRINT("Unknown DataType %lu\n", DataType);
+    return 0;
+  }
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+
+  /* Get PCI configuration space */
+  Size = HalSetBusDataByOffset(PCIConfiguration,
+                              DeviceExtension->PciDevice->BusNumber,
+                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                              Buffer,
+                              Offset,
+                              Length);
+  return Size;
+}
+
+
+static ULONG NTAPI
+InterfaceBusGetBusData(
+  IN PVOID Context,
+  IN ULONG DataType,
+  IN PVOID Buffer,
+  IN ULONG Offset,
+  IN ULONG Length)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+  ULONG Size;
+
+  DPRINT("InterfaceBusGetBusData(%p 0x%lx %p 0x%lx 0x%lx) called\n",
+    Context, DataType, Buffer, Offset, Length);
+
+  if (DataType != PCI_WHICHSPACE_CONFIG)
+  {
+    DPRINT("Unknown DataType %lu\n", DataType);
+    return 0;
+  }
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+
+  /* Get PCI configuration space */
+  Size = HalGetBusDataByOffset(PCIConfiguration,
+                              DeviceExtension->PciDevice->BusNumber,
+                              DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+                              Buffer,
+                              Offset,
+                              Length);
+  return Size;
+}
+
+static BOOLEAN NTAPI
+InterfacePciDevicePresent(
+  IN USHORT  VendorID,
+  IN USHORT  DeviceID,
+  IN UCHAR   RevisionID,
+  IN USHORT  SubVendorID,
+  IN USHORT  SubSystemID,
+  IN ULONG   Flags
+)
+{
+  DPRINT1("Checking for PCI %04X:%04X not implemented\n",
+    VendorID, DeviceID);
+
+  return FALSE;
+}
+
+static BOOLEAN NTAPI
+InterfacePciDevicePresentEx(
+  IN PVOID Context,
+  IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
+{
+  PPDO_DEVICE_EXTENSION DeviceExtension;
+
+  DPRINT1("InterfacePciDevicePresentEx(%p %p) called\n",
+    Context, Parameters);
+
+  if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
+    return FALSE;
+
+  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
+
+  DPRINT1("Checking for PCI %04X:%04X not implemented\n",
+    Parameters->VendorID, Parameters->DeviceID);
+
+  return FALSE;
+}
+
+
+static NTSTATUS
+PdoQueryInterface(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  NTSTATUS Status;
+
+  if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
+    &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
+  {
+    /* BUS_INTERFACE_STANDARD */
+    if (IrpSp->Parameters.QueryInterface.Version < 1)
+      Status = STATUS_NOT_SUPPORTED;
+    else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
+      Status = STATUS_BUFFER_TOO_SMALL;
+    else
+    {
+      PBUS_INTERFACE_STANDARD BusInterface;
+      BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
+      BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
+      BusInterface->Version = 1;
+      BusInterface->Context = DeviceObject;
+      BusInterface->InterfaceReference = InterfaceReference;
+      BusInterface->InterfaceDereference = InterfaceDereference;
+      BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
+      BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
+      BusInterface->SetBusData = InterfaceBusSetBusData;
+      BusInterface->GetBusData = InterfaceBusGetBusData;
+      Status = STATUS_SUCCESS;
+    }
+  }
+  else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
+    &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
+  {
+    /* PCI_DEVICE_PRESENT_INTERFACE */
+    if (IrpSp->Parameters.QueryInterface.Version < 1)
+      Status = STATUS_NOT_SUPPORTED;
+    else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
+      Status = STATUS_BUFFER_TOO_SMALL;
+    else
+    {
+      PPCI_DEVICE_PRESENT_INTERFACE BusInterface;
+      BusInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
+      BusInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
+      BusInterface->Version = 1;
+      BusInterface->Context = DeviceObject;
+      BusInterface->InterfaceReference = InterfaceReference;
+      BusInterface->InterfaceDereference = InterfaceDereference;
+         BusInterface->IsDevicePresent = InterfacePciDevicePresent;
+      BusInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
+      Status = STATUS_SUCCESS;
+    }
+  }
+  else
+  {
+    /* Not a supported interface */
+    return STATUS_NOT_SUPPORTED;
+  }
+
+  if (NT_SUCCESS(Status))
+  {
+    /* Add a reference for the returned interface */
+    PINTERFACE Interface;
+    Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
+    Interface->InterfaceReference(Interface->Context);
+  }
+
+  return Status;
+}
+
+
+static NTSTATUS
+PdoReadConfig(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  ULONG Size;
+
+  DPRINT("PdoReadConfig() called\n");
+
+  Size = InterfaceBusGetBusData(
+    DeviceObject,
+    IrpSp->Parameters.ReadWriteConfig.WhichSpace,
+    IrpSp->Parameters.ReadWriteConfig.Buffer,
+    IrpSp->Parameters.ReadWriteConfig.Offset,
+    IrpSp->Parameters.ReadWriteConfig.Length);
+
+  if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
+  {
+    DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
+    Irp->IoStatus.Information = 0;
+    return STATUS_UNSUCCESSFUL;
+  }
+
+  Irp->IoStatus.Information = Size;
+
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+PdoWriteConfig(
+  IN PDEVICE_OBJECT DeviceObject,
+  IN PIRP Irp,
+  PIO_STACK_LOCATION IrpSp)
+{
+  ULONG Size;
+
+  DPRINT1("PdoWriteConfig() called\n");
+
+  /* Get PCI configuration space */
+  Size = InterfaceBusSetBusData(
+    DeviceObject,
+    IrpSp->Parameters.ReadWriteConfig.WhichSpace,
+    IrpSp->Parameters.ReadWriteConfig.Buffer,
+    IrpSp->Parameters.ReadWriteConfig.Offset,
+    IrpSp->Parameters.ReadWriteConfig.Length);
+
+  if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
+  {
+    DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
+    Irp->IoStatus.Information = 0;
+    return STATUS_UNSUCCESSFUL;
+  }
+
+  Irp->IoStatus.Information = Size;
+
+  return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
 PdoSetPower(
   IN PDEVICE_OBJECT DeviceObject,
   IN PIRP Irp,
@@ -193,12 +1178,6 @@ PdoPnpControl(
 
   switch (IrpSp->MinorFunction) {
 #if 0
-  case IRP_MN_CANCEL_REMOVE_DEVICE:
-    break;
-
-  case IRP_MN_CANCEL_STOP_DEVICE:
-    break;
-
   case IRP_MN_DEVICE_USAGE_NOTIFICATION:
     break;
 
@@ -218,48 +1197,66 @@ PdoPnpControl(
   case IRP_MN_QUERY_DEVICE_RELATIONS:
     /* FIXME: Possibly handle for RemovalRelations */
     break;
+#endif
 
   case IRP_MN_QUERY_DEVICE_TEXT:
+    DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
+    Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
     break;
-#endif
 
   case IRP_MN_QUERY_ID:
+    DPRINT("IRP_MN_QUERY_ID received\n");
     Status = PdoQueryId(DeviceObject, Irp, IrpSp);
     break;
 
 #if 0
   case IRP_MN_QUERY_PNP_DEVICE_STATE:
     break;
-
-  case IRP_MN_QUERY_REMOVE_DEVICE:
-    break;
+#endif
 
   case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
+    DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
+    Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
     break;
 
   case IRP_MN_QUERY_RESOURCES:
+    DPRINT("IRP_MN_QUERY_RESOURCES received\n");
+    Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
     break;
 
-  case IRP_MN_QUERY_STOP_DEVICE:
+#if 0
+  case IRP_MN_SET_LOCK:
     break;
+#endif
 
+  case IRP_MN_START_DEVICE:
+  case IRP_MN_QUERY_STOP_DEVICE:
+  case IRP_MN_CANCEL_STOP_DEVICE:
+  case IRP_MN_STOP_DEVICE:
+  case IRP_MN_QUERY_REMOVE_DEVICE:
+  case IRP_MN_CANCEL_REMOVE_DEVICE:
   case IRP_MN_REMOVE_DEVICE:
+  case IRP_MN_SURPRISE_REMOVAL:
+    Status = STATUS_SUCCESS;
     break;
 
-  case IRP_MN_SET_LOCK:
+  case IRP_MN_QUERY_INTERFACE:
+    DPRINT("IRP_MN_QUERY_INTERFACE received\n");
+    Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
     break;
 
-  case IRP_MN_START_DEVICE:
+  case IRP_MN_READ_CONFIG:
+    DPRINT("IRP_MN_READ_CONFIG received\n");
+    Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
     break;
 
-  case IRP_MN_STOP_DEVICE:
+  case IRP_MN_WRITE_CONFIG:
+    DPRINT("IRP_MN_WRITE_CONFIG received\n");
+    Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
     break;
 
-  case IRP_MN_SURPRISE_REMOVAL:
-    break;
-#endif
   default:
-    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
+    DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);
     break;
   }