mirror of
https://github.com/reactos/reactos.git
synced 2026-09-08 18:30:51 +08:00
[PCIX] Preperation for initial PCIX Arbiters to be enabled (#9479)
* [PCIX] Use the bridge's parent bus in the IRQ translator constructor * [PCIX] Stop the limit descriptor scan from running off the array * [PCIX] Build a real resource requirements list for each function * [PCIX] Skip the right descriptors when draining a device-private group * [PCIX] Record assigned resources against the BAR they satisfy * [PCIX] Program device BARs with their arbitrated addresses --------- Co-authored-by: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito@reactos.org>
This commit is contained in:
@@ -81,13 +81,13 @@ tranirq_Constructor(IN PVOID DeviceExtension,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* It's not, so we have to get the root bus' bus number instead */
|
||||
#if 0 // when have PDO commit
|
||||
ParentBus = FdoExtension->PhysicalDeviceObject->DeviceExtension->ParentFdoExtension->BaseBus;
|
||||
/* It's not, so the translator is rooted on the bus the bridge sits on */
|
||||
PPCI_PDO_EXTENSION PdoExtension = FdoExtension->PhysicalDeviceObject->DeviceExtension;
|
||||
ASSERT_PDO(PdoExtension);
|
||||
ParentBus = PdoExtension->ParentFdoExtension->BaseBus;
|
||||
ParentInterface = PCIBus;
|
||||
DPRINT1(" Is bridge FDO, parent bus %x, secondary bus %x\n",
|
||||
ParentBus, BaseBus);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Now call the legacy HAL interface to get the correct translator */
|
||||
|
||||
@@ -283,10 +283,73 @@ NTAPI
|
||||
Device_ChangeResourceSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
IN PPCI_COMMON_HEADER PciData)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(PdoExtension);
|
||||
UNREFERENCED_PARAMETER(PciData);
|
||||
/* Not yet implemented */
|
||||
UNIMPLEMENTED_DBGBREAK();
|
||||
PPCI_FUNCTION_RESOURCES Resources;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
|
||||
PULONG BarArray;
|
||||
ULONG Bar, BarMask, i;
|
||||
|
||||
Resources = PdoExtension->Resources;
|
||||
if (!Resources)
|
||||
return;
|
||||
|
||||
/* Write each BAR back with the address that was arbitrated for it */
|
||||
BarArray = PciData->u.type0.BaseAddresses;
|
||||
for (i = 0; i <= PCI_TYPE0_ADDRESSES; i++)
|
||||
{
|
||||
CmDescriptor = &Resources->Current[i];
|
||||
|
||||
if (i < PCI_TYPE0_ADDRESSES)
|
||||
{
|
||||
/* A BAR the function does not implement reads back as zero */
|
||||
Bar = BarArray[i];
|
||||
if (!(Bar & ~PCI_ADDRESS_IO_SPACE)) continue;
|
||||
|
||||
/* Work out which bits of this BAR are the address */
|
||||
if (Bar & PCI_ADDRESS_IO_SPACE)
|
||||
{
|
||||
BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
|
||||
}
|
||||
else
|
||||
{
|
||||
BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
|
||||
|
||||
/* A legacy BAR only decodes the low 20 bits of the address */
|
||||
if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT)
|
||||
{
|
||||
BarMask = 0xFFFF0;
|
||||
}
|
||||
}
|
||||
|
||||
BarArray[i] = (Bar & ~BarMask) |
|
||||
(CmDescriptor->u.Memory.Start.LowPart & BarMask);
|
||||
|
||||
/* A 64-bit BAR keeps the high half of its address in the next one */
|
||||
if (!(Bar & PCI_ADDRESS_IO_SPACE) &&
|
||||
((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT))
|
||||
{
|
||||
ASSERT((i + 1) < PCI_TYPE0_ADDRESSES);
|
||||
BarArray[i + 1] = CmDescriptor->u.Memory.Start.HighPart;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The ROM BAR decodes only while its enable bit is set */
|
||||
Bar = PciData->u.type0.ROMBaseAddress;
|
||||
if (CmDescriptor->Type == CmResourceTypeNull)
|
||||
{
|
||||
PciData->u.type0.ROMBaseAddress = Bar & ~PCI_ROMADDRESS_ENABLED;
|
||||
}
|
||||
else
|
||||
{
|
||||
PciData->u.type0.ROMBaseAddress =
|
||||
(Bar & ~PCI_ADDRESS_ROM_ADDRESS_MASK) |
|
||||
(CmDescriptor->u.Memory.Start.LowPart &
|
||||
PCI_ADDRESS_ROM_ADDRESS_MASK) |
|
||||
PCI_ROMADDRESS_ENABLED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
||||
@@ -56,11 +56,12 @@ 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;
|
||||
PCM_PARTIAL_RESOURCE_DESCRIPTOR CurrentDescriptor;
|
||||
CM_PARTIAL_RESOURCE_DESCRIPTOR ResourceArray[7];
|
||||
ULONG BarIndex;
|
||||
PCM_FULL_RESOURCE_DESCRIPTOR FullList;
|
||||
BOOLEAN DrainPartial, RangeChange;
|
||||
BOOLEAN RangeChange;
|
||||
ULONG DrainPartial;
|
||||
ULONG i, j;
|
||||
PPCI_FUNCTION_RESOURCES PciResources;
|
||||
PAGED_CODE();
|
||||
@@ -72,6 +73,11 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
Partial = NULL;
|
||||
InterruptResource = NULL;
|
||||
RangeChange = FALSE;
|
||||
BarIndex = 0;
|
||||
|
||||
/* The limits say which BARs this function implements, so the walk below
|
||||
* can tell which BAR each assigned descriptor belongs to */
|
||||
PciResources = PdoExtension->Resources;
|
||||
|
||||
/* Check if there's not actually any resources */
|
||||
if (!(ResourceList) || !(ResourceList->Count))
|
||||
@@ -91,8 +97,7 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
for (i = 0; i < ResourceList->Count; i++)
|
||||
{
|
||||
/* Initialize loop variables */
|
||||
DrainPartial = FALSE;
|
||||
BaseResource = NULL;
|
||||
DrainPartial = 0;
|
||||
|
||||
/* Loop the partial descriptors */
|
||||
Partial = FullList->PartialResourceList.PartialDescriptors;
|
||||
@@ -101,8 +106,8 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
/* 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--;
|
||||
Partial = CmiGetNextPartialDescriptor(Partial);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -122,9 +127,22 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set it as the base */
|
||||
ASSERT(BaseResource == NULL);
|
||||
BaseResource = Partial;
|
||||
/*
|
||||
* The assigned descriptors come back in the order the
|
||||
* requirements list asked for them, so walking the limits
|
||||
* in that same order says which BAR this one satisfies.
|
||||
*/
|
||||
if (PciResources)
|
||||
{
|
||||
while ((BarIndex < RTL_NUMBER_OF(ResourceArray)) &&
|
||||
(PciResources->Limit[BarIndex].Type == CmResourceTypeNull))
|
||||
{
|
||||
BarIndex++;
|
||||
}
|
||||
|
||||
if (BarIndex < RTL_NUMBER_OF(ResourceArray))
|
||||
ResourceArray[BarIndex++] = *Partial;
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* Interrupt resource */
|
||||
@@ -167,10 +185,7 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
|
||||
/* 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;
|
||||
@@ -181,34 +196,25 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
}
|
||||
|
||||
/* We should be starting a new list now */
|
||||
ASSERT(BaseResource == NULL);
|
||||
FullList = (PVOID)Partial;
|
||||
}
|
||||
|
||||
/* Check the current assigned PCI resources */
|
||||
PciResources = PdoExtension->Resources;
|
||||
/* A function with no discovered resources has nothing to update */
|
||||
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++)
|
||||
for (i = 0; i < RTL_NUMBER_OF(ResourceArray); 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)))
|
||||
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;
|
||||
@@ -232,9 +238,8 @@ PciComputeNewCurrentSettings(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
|
||||
/* 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;
|
||||
CurrentDescriptor->u.Generic.Start = Partial->u.Generic.Start;
|
||||
CurrentDescriptor->u.Generic.Length = Partial->u.Generic.Length;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -562,10 +567,35 @@ PciBuildRequirementsList(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
OUT PIO_RESOURCE_REQUIREMENTS_LIST* Buffer)
|
||||
{
|
||||
PIO_RESOURCE_REQUIREMENTS_LIST RequirementsList;
|
||||
PIO_RESOURCE_DESCRIPTOR Descriptor, Limit;
|
||||
PCI_CONFIGURATOR_CONTEXT Context;
|
||||
ULONG Count, i;
|
||||
BOOLEAN HaveInterrupt;
|
||||
|
||||
UNREFERENCED_PARAMETER(PdoExtension);
|
||||
UNREFERENCED_PARAMETER(PciData);
|
||||
PAGED_CODE();
|
||||
|
||||
/* Count the BAR limits that resource discovery found for this function */
|
||||
Count = 0;
|
||||
if (PdoExtension->Resources)
|
||||
{
|
||||
for (i = 0; i < (PCI_TYPE0_ADDRESSES + 1); i++)
|
||||
{
|
||||
if (PdoExtension->Resources->Limit[i].Type != CmResourceTypeNull)
|
||||
Count++;
|
||||
}
|
||||
}
|
||||
|
||||
/* A device with an interrupt pin also needs a line routed to it */
|
||||
HaveInterrupt = (PdoExtension->InterruptPin) &&
|
||||
!(PdoExtension->HackFlags & PCI_HACK_NO_ENUM_AT_ALL);
|
||||
if (HaveInterrupt)
|
||||
Count++;
|
||||
|
||||
/* And a bridge with legacy decodes enabled needs those ranges locked down */
|
||||
Count += PdoExtension->AdditionalResourceCount;
|
||||
|
||||
/* Check if the function turned out to need nothing after all */
|
||||
if (!Count)
|
||||
{
|
||||
/* There aren't, so use the zero descriptor */
|
||||
RequirementsList = PciZeroIoResourceRequirements;
|
||||
@@ -579,11 +609,57 @@ PciBuildRequirementsList(IN PPCI_PDO_EXTENSION PdoExtension,
|
||||
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;
|
||||
}
|
||||
|
||||
RequirementsList = PciAllocateIoRequirementsList(Count,
|
||||
PdoExtension->ParentFdoExtension->BaseBus,
|
||||
PdoExtension->Slot.u.AsULONG);
|
||||
if (!RequirementsList)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
Descriptor = RequirementsList->List[0].Descriptors;
|
||||
|
||||
/* Emit one descriptor per BAR that decoded something during discovery */
|
||||
if (PdoExtension->Resources)
|
||||
{
|
||||
Limit = PdoExtension->Resources->Limit;
|
||||
for (i = 0; i < (PCI_TYPE0_ADDRESSES + 1); i++)
|
||||
{
|
||||
/* Skip the BARs this function does not implement */
|
||||
if (Limit[i].Type == CmResourceTypeNull)
|
||||
continue;
|
||||
|
||||
/* A BAR decodes for one function only, so it cannot be shared */
|
||||
*Descriptor = Limit[i];
|
||||
Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
||||
Descriptor++;
|
||||
}
|
||||
}
|
||||
|
||||
if (HaveInterrupt)
|
||||
{
|
||||
Descriptor->Type = CmResourceTypeInterrupt;
|
||||
Descriptor->ShareDisposition = CmResourceShareShared;
|
||||
Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
||||
Descriptor->u.Interrupt.MinimumVector = 0;
|
||||
Descriptor->u.Interrupt.MaximumVector = MAXULONG;
|
||||
Descriptor++;
|
||||
}
|
||||
|
||||
/* And finally any extra ranges this kind of function decodes on the side */
|
||||
if (PdoExtension->AdditionalResourceCount)
|
||||
{
|
||||
RtlZeroMemory(&Context, sizeof(Context));
|
||||
Context.PdoExtension = PdoExtension;
|
||||
Context.Current = PciData;
|
||||
PciConfigurators[PdoExtension->HeaderType].
|
||||
GetAdditionalResourceDescriptors(&Context, PciData, Descriptor);
|
||||
}
|
||||
|
||||
*Buffer = RequirementsList;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -1470,8 +1546,8 @@ PcipGetFunctionLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
|
||||
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 is a null descriptor, have all of them been scanned now? */
|
||||
if (IoDescriptor == &PdoExtension->Resources->Limit[0])
|
||||
{
|
||||
/* This means the descriptor is NULL, which means discovery failed */
|
||||
DPRINT1("PCI Resources fail!\n");
|
||||
|
||||
Reference in New Issue
Block a user