+/*
+ * Find the extent of a PCI decode..
+ */
+static ULONG STDCALL
+PciSize(ULONG Base, ULONG Mask)
+{
+ ULONG Size = Mask & Base; /* Find the significant bits */
+ Size = Size & ~(Size - 1); /* Get the lowest of them to find the decode size */
+ return Size;
+}
+
+static NTSTATUS STDCALL
+HalpAssignPciSlotResources(IN PBUS_HANDLER BusHandler,
+ IN ULONG BusNumber,
+ IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+ UINT Address;
+ UINT NoAddresses;
+ ULONG BaseAddresses[PCI_TYPE0_ADDRESSES];
+ ULONG Size[PCI_TYPE0_ADDRESSES];
+ NTSTATUS Status = STATUS_SUCCESS;
+ UCHAR Offset;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+
+ /* FIXME: Should handle 64-bit addresses */
+
+ /* Read the PCI configuration space for the device and store base address and
+ size information in temporary storage. Count the number of valid base addresses */
+ NoAddresses = 0;
+ for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
+ {
+ Offset = offsetof(PCI_COMMON_CONFIG, u.type0.BaseAddresses[Address]);
+ Status = ReadPciConfigUlong(BusNumber, SlotNumber,
+ Offset, BaseAddresses + Address);
+ if (! NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ if (0xffffffff == BaseAddresses[Address])
+ {
+ BaseAddresses[Address] = 0;
+ }
+ if (0 != BaseAddresses[Address])
+ {
+ NoAddresses++;
+ Status = WritePciConfigUlong(BusNumber, SlotNumber, Offset, 0xffffffff);
+ if (! NT_SUCCESS(Status))
+ {
+ WritePciConfigUlong(BusNumber, SlotNumber, Offset, BaseAddresses[Address]);
+ return Status;
+ }
+ Status = ReadPciConfigUlong(BusNumber, SlotNumber,
+ Offset, Size + Address);
+ if (! NT_SUCCESS(Status))
+ {
+ WritePciConfigUlong(BusNumber, SlotNumber, Offset, BaseAddresses[Address]);
+ return Status;
+ }
+ Status = WritePciConfigUlong(BusNumber, SlotNumber, Offset, BaseAddresses[Address]);
+ if (! NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ }
+ }
+
+ /* Allocate output buffer and initialize */
+ *AllocatedResources = ExAllocatePoolWithTag(PagedPool,
+ sizeof(CM_RESOURCE_LIST) +
+ (NoAddresses - 1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR),
+ TAG_PCI);
+ if (NULL == *AllocatedResources)
+ {
+ return STATUS_NO_MEMORY;
+ }
+ (*AllocatedResources)->Count = 1;
+ (*AllocatedResources)->List[0].InterfaceType = PCIBus;
+ (*AllocatedResources)->List[0].BusNumber = BusNumber;
+ (*AllocatedResources)->List[0].PartialResourceList.Version = 1;
+ (*AllocatedResources)->List[0].PartialResourceList.Revision = 1;
+ (*AllocatedResources)->List[0].PartialResourceList.Count = NoAddresses;
+ Descriptor = (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors;
+
+ /* Store configuration information */
+ for (Address = 0; Address < PCI_TYPE0_ADDRESSES; Address++)
+ {
+ if (0 != BaseAddresses[Address])
+ {
+ if (PCI_BASE_ADDRESS_SPACE_MEMORY ==
+ (BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
+ {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE; /* FIXME Just a guess */
+ Descriptor->u.Memory.Start.QuadPart = (BaseAddresses[Address] & PCI_BASE_ADDRESS_MEM_MASK);
+ Descriptor->u.Memory.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_MEM_MASK);
+ }
+ else if (PCI_BASE_ADDRESS_SPACE_IO ==
+ (BaseAddresses[Address] & PCI_BASE_ADDRESS_SPACE))
+ {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive; /* FIXME I have no idea... */
+ Descriptor->Flags = CM_RESOURCE_PORT_IO; /* FIXME Just a guess */
+ Descriptor->u.Port.Start.QuadPart = BaseAddresses[Address] &= PCI_BASE_ADDRESS_IO_MASK;
+ Descriptor->u.Port.Length = PciSize(Size[Address], PCI_BASE_ADDRESS_IO_MASK & 0xffff);
+ }
+ else
+ {
+ assert(FALSE);
+ return STATUS_UNSUCCESSFUL;
+ }
+ Descriptor++;
+ }
+ }
+
+ assert(Descriptor == (*AllocatedResources)->List[0].PartialResourceList.PartialDescriptors + NoAddresses);
+
+ /* FIXME: Should store the resources in the registry resource map */
+
+ return Status;
+}
+