#define DBGPRINT(...)
#endif
+#define PCI_ADDRESS_MEMORY_ADDRESS_MASK_64 0xfffffffffffffff0ull
+#define PCI_ADDRESS_IO_ADDRESS_MASK_64 0xfffffffffffffffcull
+
/*** PRIVATE *****************************************************************/
static NTSTATUS
return STATUS_SUCCESS;
}
-
static BOOLEAN
-PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
- ULONG Offset,
- PULONG Base,
- PULONG Length,
- PULONG Flags)
+PdoReadPciBar(PPDO_DEVICE_EXTENSION DeviceExtension,
+ ULONG Offset,
+ PULONG OriginalValue,
+ PULONG NewValue)
{
- 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));
+ ULONG AllOnes;
+
+ /* Read the original value */
+ Size = HalGetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->PciDevice->BusNumber,
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ OriginalValue,
+ Offset,
+ sizeof(ULONG));
if (Size != sizeof(ULONG))
{
DPRINT1("Wrong size %lu\n", Size);
return FALSE;
}
-
- BaseValue = (OrigValue & PCI_ADDRESS_IO_SPACE)
- ? (OrigValue & PCI_ADDRESS_IO_ADDRESS_MASK)
- : (OrigValue & PCI_ADDRESS_MEMORY_ADDRESS_MASK);
-
- *Base = BaseValue;
-
- /* Set magic value */
- NewValue = MAXULONG;
- Size= HalSetBusDataByOffset(PCIConfiguration,
- DeviceExtension->PciDevice->BusNumber,
- DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
- &NewValue,
- Offset,
- sizeof(ULONG));
+
+ /* Write all ones to determine which bits are held to zero */
+ AllOnes = MAXULONG;
+ Size = HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->PciDevice->BusNumber,
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ &AllOnes,
+ 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));
+ 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);
}
/* Restore original value */
- Size= HalSetBusDataByOffset(PCIConfiguration,
- DeviceExtension->PciDevice->BusNumber,
- DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
- &OrigValue,
- Offset,
- sizeof(ULONG));
+ Size = HalSetBusDataByOffset(PCIConfiguration,
+ DeviceExtension->PciDevice->BusNumber,
+ DeviceExtension->PciDevice->SlotNumber.u.AsULONG,
+ OriginalValue,
+ Offset,
+ sizeof(ULONG));
if (Size != sizeof(ULONG))
{
DPRINT1("Wrong size %lu\n", Size);
return FALSE;
}
+
+ return TRUE;
+}
- if (NewValue == 0)
- {
- DPRINT("Unused address register\n");
- *Base = 0;
- *Length = 0;
- *Flags = 0;
- return TRUE;
- }
-
- XLength = ~((NewValue & PCI_ADDRESS_IO_SPACE)
- ? (NewValue & PCI_ADDRESS_IO_ADDRESS_MASK)
- : (NewValue & PCI_ADDRESS_MEMORY_ADDRESS_MASK)) + 1;
-
-#if 0
- DbgPrint("BaseAddress 0x%08lx Length 0x%08lx",
- BaseValue, XLength);
-
- if (NewValue & PCI_ADDRESS_IO_SPACE)
+static BOOLEAN
+PdoGetRangeLength(PPDO_DEVICE_EXTENSION DeviceExtension,
+ UCHAR Bar,
+ PULONGLONG Base,
+ PULONGLONG Length,
+ PULONG Flags,
+ PUCHAR NextBar,
+ PULONGLONG MaximumAddress)
+{
+ union {
+ struct {
+ ULONG Bar0;
+ ULONG Bar1;
+ } Bars;
+ ULONGLONG Bar;
+ } OriginalValue;
+ union {
+ struct {
+ ULONG Bar0;
+ ULONG Bar1;
+ } Bars;
+ ULONGLONG Bar;
+ } NewValue;
+ ULONG Offset;
+
+ /* Compute the offset of this BAR in PCI config space */
+ Offset = 0x10 + Bar * 4;
+
+ /* Assume this is a 32-bit BAR until we find wrong */
+ *NextBar = Bar + 1;
+
+ /* Initialize BAR values to zero */
+ OriginalValue.Bar = 0ULL;
+ NewValue.Bar = 0ULL;
+
+ /* Read the first BAR */
+ if (!PdoReadPciBar(DeviceExtension, Offset,
+ &OriginalValue.Bars.Bar0,
+ &NewValue.Bars.Bar0))
{
- DbgPrint(" IO range");
+ return FALSE;
}
- else
+
+ /* Check if this is a memory BAR */
+ if (!(OriginalValue.Bars.Bar0 & PCI_ADDRESS_IO_SPACE))
{
- DbgPrint(" Memory range");
- if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 0)
+ /* Write the maximum address if the caller asked for it */
+ if (MaximumAddress != NULL)
{
- DbgPrint(" in 32-Bit address space");
+ if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_32BIT)
+ {
+ *MaximumAddress = 0x00000000FFFFFFFFULL;
+ }
+ else if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT)
+ {
+ *MaximumAddress = 0x00000000000FFFFFULL;
+ }
+ else if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+ {
+ *MaximumAddress = 0xFFFFFFFFFFFFFFFFULL;
+ }
}
- else if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 2)
+
+ /* Check if this is a 64-bit BAR */
+ if ((OriginalValue.Bars.Bar0 & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
{
- DbgPrint(" below 1BM ");
+ /* We've now consumed the next BAR too */
+ *NextBar = Bar + 2;
+
+ /* Read the next BAR */
+ if (!PdoReadPciBar(DeviceExtension, Offset + 4,
+ &OriginalValue.Bars.Bar1,
+ &NewValue.Bars.Bar1))
+ {
+ return FALSE;
+ }
}
- else if ((NewValue & PCI_ADDRESS_MEMORY_TYPE_MASK) == 4)
+ }
+ else
+ {
+ /* Write the maximum I/O port address */
+ if (MaximumAddress != NULL)
{
- DbgPrint(" in 64-Bit address space");
+ *MaximumAddress = 0x00000000FFFFFFFFULL;
}
+ }
- if (NewValue & PCI_ADDRESS_MEMORY_PREFETCHABLE)
- {
- DbgPrint(" prefetchable");
- }
+ if (NewValue.Bar == 0)
+ {
+ DPRINT("Unused address register\n");
+ *Base = 0;
+ *Length = 0;
+ *Flags = 0;
+ return TRUE;
}
+
+ *Base = OriginalValue.Bar & PCI_ADDRESS_MEMORY_ADDRESS_MASK_64;
- DbgPrint("\n");
-#endif
+ *Length = ~((NewValue.Bar & PCI_ADDRESS_IO_SPACE)
+ ? (NewValue.Bar & PCI_ADDRESS_IO_ADDRESS_MASK_64)
+ : (NewValue.Bar & PCI_ADDRESS_MEMORY_ADDRESS_MASK_64)) + 1;
- *Length = XLength;
- *Flags = (NewValue & PCI_ADDRESS_IO_SPACE)
- ? (NewValue & ~PCI_ADDRESS_IO_ADDRESS_MASK)
- : (NewValue & ~PCI_ADDRESS_MEMORY_ADDRESS_MASK);
+ *Flags = (NewValue.Bar & PCI_ADDRESS_IO_SPACE)
+ ? (NewValue.Bar & ~PCI_ADDRESS_IO_ADDRESS_MASK_64)
+ : (NewValue.Bar & ~PCI_ADDRESS_MEMORY_ADDRESS_MASK_64);
return TRUE;
}
ULONG Size;
ULONG ResCount = 0;
ULONG ListSize;
- ULONG i;
- ULONG Base;
- ULONG Length;
+ UCHAR Bar;
+ ULONGLONG Base;
+ ULONGLONG Length;
ULONG Flags;
+ ULONGLONG MaximumAddress;
UNREFERENCED_PARAMETER(IrpSp);
DPRINT("PdoQueryResourceRequirements() called\n");
ResCount = 0;
if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
{
- for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
+ &Flags,
+ &Bar,
+ NULL))
break;
if (Length != 0)
}
else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
{
- for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
+ &Flags,
+ &Bar,
+ NULL))
break;
if (Length != 0)
Descriptor = &ResourceList->List[0].Descriptors[0];
if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
{
- for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
+ &Flags,
+ &Bar,
+ &MaximumAddress))
{
DPRINT1("PdoGetRangeLength() failed\n");
break;
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);
+ Descriptor->u.Port.MinimumAddress.QuadPart = Base;
+ Descriptor->u.Port.MaximumAddress.QuadPart = Base + Length - 1;
}
else
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
+ (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
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->u.Memory.MinimumAddress.QuadPart = Base;
+ Descriptor->u.Memory.MaximumAddress.QuadPart = Base + Length - 1;
}
Descriptor++;
Descriptor->u.Port.Length = Length;
Descriptor->u.Port.Alignment = Length;
- Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
- Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
+ Descriptor->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
}
else
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
+ (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
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->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
}
Descriptor++;
}
}
else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
{
- for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
+ &Flags,
+ &Bar,
+ &MaximumAddress))
{
DPRINT1("PdoGetRangeLength() failed\n");
break;
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);
+ Descriptor->u.Port.MinimumAddress.QuadPart = Base;
+ Descriptor->u.Port.MaximumAddress.QuadPart = Base + Length - 1;
}
else
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
+ (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
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->u.Memory.MinimumAddress.QuadPart = Base;
+ Descriptor->u.Memory.MaximumAddress.QuadPart = Base + Length - 1;
}
Descriptor++;
Descriptor->u.Port.Length = Length;
Descriptor->u.Port.Alignment = Length;
- Descriptor->u.Port.MinimumAddress.QuadPart = (ULONGLONG)0;
- Descriptor->u.Port.MaximumAddress.QuadPart = (ULONGLONG)0x00000000FFFFFFFF;
+ Descriptor->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
}
else
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
+ (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
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->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = MaximumAddress;
}
Descriptor++;
}
ULONG Size;
ULONG ResCount = 0;
ULONG ListSize;
- ULONG i;
- ULONG Base;
- ULONG Length;
+ UCHAR Bar;
+ ULONGLONG Base;
+ ULONGLONG Length;
ULONG Flags;
DPRINT("PdoQueryResources() called\n");
ResCount = 0;
if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
{
- for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
+ &Flags,
+ &Bar,
+ NULL))
break;
if (Length)
}
else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
{
- for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
+ &Flags,
+ &Bar,
+ NULL))
break;
if (Length != 0)
Descriptor = &PartialList->PartialDescriptors[0];
if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_DEVICE_TYPE)
{
- for (i = 0; i < PCI_TYPE0_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE0_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
- {
- DPRINT1("PdoGetRangeLength() failed\n");
+ &Flags,
+ &Bar,
+ NULL))
break;
- }
if (Length == 0)
{
{
Descriptor->Type = CmResourceTypePort;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO |
+ CM_RESOURCE_PORT_16_BIT_DECODE |
+ CM_RESOURCE_PORT_POSITIVE_DECODE;
Descriptor->u.Port.Start.QuadPart = (ULONGLONG)Base;
Descriptor->u.Port.Length = Length;
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
+ (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
Descriptor->u.Memory.Start.QuadPart = (ULONGLONG)Base;
Descriptor->u.Memory.Length = Length;
}
else if (PCI_CONFIGURATION_TYPE(&PciConfig) == PCI_BRIDGE_TYPE)
{
- for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ for (Bar = 0; Bar < PCI_TYPE1_ADDRESSES;)
{
if (!PdoGetRangeLength(DeviceExtension,
- 0x10 + i * 4,
+ Bar,
&Base,
&Length,
- &Flags))
- {
- DPRINT1("PdoGetRangeLength() failed\n");
+ &Flags,
+ &Bar,
+ NULL))
break;
- }
if (Length == 0)
{
{
Descriptor->Type = CmResourceTypePort;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO |
+ CM_RESOURCE_PORT_16_BIT_DECODE |
+ CM_RESOURCE_PORT_POSITIVE_DECODE;
Descriptor->u.Port.Start.QuadPart = (ULONGLONG)Base;
Descriptor->u.Port.Length = Length;
{
Descriptor->Type = CmResourceTypeMemory;
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
- Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE |
+ (Flags & PCI_ADDRESS_MEMORY_PREFETCHABLE) ? CM_RESOURCE_MEMORY_PREFETCHABLE : 0;
Descriptor->u.Memory.Start.QuadPart = (ULONGLONG)Base;
Descriptor->u.Memory.Length = Length;