+ DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
+
+ /* Get PCI configuration space */
+ Size= HalGetBusData(PCIConfiguration,
+ DeviceExtension->BusNumber,
+ DeviceExtension->SlotNumber.u.AsULONG,
+ &PciConfig,
+ sizeof(PCI_COMMON_CONFIG));
+ DPRINT("Size %lu\n", Size);
+ if (Size < sizeof(PCI_COMMON_CONFIG))
+ {
+ Irp->IoStatus.Information = 0;
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ DPRINT("Command register: 0x%04hx\n", PciConfig.Command);
+
+ /* Count required resource descriptors */
+ ResCount = 0;
+ if ((PciConfig.HeaderType & 0x7F) == 0)
+ {
+ for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ {
+ if (!PdoGetRangeLength(DeviceExtension,
+ 0x10 + i * 4,
+ &Base,
+ &Length,
+ &Flags))
+ break;
+
+ ResCount += 2;
+ }
+
+ /* FIXME: Check ROM address */
+
+ if (PciConfig.u.type0.InterruptPin != 0)
+ ResCount++;
+ }
+ else if ((PciConfig.HeaderType & 0x7F) == 1)
+ {
+ for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ {
+ if (!PdoGetRangeLength(DeviceExtension,
+ 0x10 + i * 4,
+ &Base,
+ &Length,
+ &Flags))
+ break;
+
+ ResCount += 2;
+ }
+ }
+ else
+ {
+ DPRINT1("Unsupported header type %u\n", PciConfig.HeaderType);
+ }
+
+ 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));
+ }
+
+ DPRINT1("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->AlternativeLists = 1;
+
+ ResourceList->List[0].Version = 1;
+ ResourceList->List[0].Revision = 1;
+ ResourceList->List[0].Count = ResCount;
+
+ Descriptor = &ResourceList->List[0].Descriptors[0];
+ if ((PciConfig.HeaderType & 0x7F) == 0)
+ {
+ 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");
+ break;
+ }
+
+ /* 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;
+
+ 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;
+
+ Descriptor->u.Port.Length = Length;
+ Descriptor->u.Port.Alignment = Length;
+ Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(ULONG)-1;
+ }
+ 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)(ULONG)-1;
+ }
+ Descriptor++;
+ }
+
+ /* FIXME: Check ROM address */
+
+ if (PciConfig.u.type0.InterruptPin != 0)
+ {
+ 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 ((PciConfig.HeaderType & 0x7F) == 1)
+ {
+ 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");
+ break;
+ }
+
+ /* 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;
+
+ 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;
+
+ Descriptor->u.Port.Length = Length;
+ Descriptor->u.Port.Alignment = Length;
+ Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)(ULONG)-1;
+ }
+ 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++;
+ }
+ }
+
+ Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
+
+ return STATUS_SUCCESS;