Author: evb
Date: Tue Jul 27 03:24:24 2010
New Revision: 48298
URL:
http://svn.reactos.org/svn/reactos?rev=48298&view=rev
Log:
Add all pci bridge control function (PciBridgeIoBase, PciBridgeIoLimit,
PciBridgeMemoryBase, PciBridgeMemoryLimit, PciBridgePrefetchMemoryBase,
PciBridgePrefetchMemoryLimit, PciBridgeMemoryWorstCasealignment,
PciBridgeIsPositiveDecode, PciBridgeIsSubtractiveDecode)
More support ICH0/1/2/3/4 hub
Add all PCI2PCI bridge limit/current resource codes (PPBridge_*), now is BAR setup okay,
and Device_* must be implement
Support ISA+VGA legacy decode, 20+64-bit decode, ROM BAR, prefetch BAR
Modified:
trunk/reactos/drivers/bus/pcix/pci.h
trunk/reactos/drivers/bus/pcix/pci/ppbridge.c
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Tue Jul 27 03:24:24 2010
@@ -1072,6 +1072,14 @@
BOOLEAN
NTAPI
+PciCreateIoDescriptorFromBarLimit(
+ PIO_RESOURCE_DESCRIPTOR ResourceDescriptor,
+ IN PULONG BarArray,
+ IN BOOLEAN Rom
+);
+
+BOOLEAN
+NTAPI
PciIsSlotPresentInParentMethod(
IN PPCI_PDO_EXTENSION PdoExtension,
IN ULONG Method
Modified: trunk/reactos/drivers/bus/pcix/pci/ppbridge.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci/ppbri…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci/ppbridge.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci/ppbridge.c [iso-8859-1] Tue Jul 27 03:24:24 2010
@@ -16,36 +16,612 @@
/* FUNCTIONS ******************************************************************/
+ULONG
+NTAPI
+PciBridgeIoBase(IN PPCI_COMMON_HEADER PciData)
+{
+ BOOLEAN Is32Bit;
+ ULONG Base, IoBase;
+ ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+ /* Get the base */
+ Base = PciData->u.type1.IOLimit;
+
+ /* Low bit specifies 32-bit address, top bits specify the base */
+ Is32Bit = (Base & 0xF) == 1;
+ IoBase = (Base & 0xF0) << 8;
+
+ /* Is it 32-bit? */
+ if (Is32Bit)
+ {
+ /* Read the upper 16-bits from the other register */
+ IoBase |= PciData->u.type1.IOBaseUpper16 << 16;
+ ASSERT(PciData->u.type1.IOLimit & 0x1);
+ }
+
+ /* Return the base address */
+ return IoBase;
+}
+
+ULONG
+NTAPI
+PciBridgeIoLimit(IN PPCI_COMMON_HEADER PciData)
+{
+ BOOLEAN Is32Bit;
+ ULONG Limit, IoLimit;
+ ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+ /* Get the limit */
+ Limit = PciData->u.type1.IOLimit;
+
+ /* Low bit specifies 32-bit address, top bits specify the limit */
+ Is32Bit = (Limit & 0xF) == 1;
+ IoLimit = (Limit & 0xF0) << 8;
+
+ /* Is it 32-bit? */
+ if (Is32Bit)
+ {
+ /* Read the upper 16-bits from the other register */
+ IoLimit |= PciData->u.type1.IOLimitUpper16 << 16;
+ ASSERT(PciData->u.type1.IOBase & 0x1);
+ }
+
+ /* Return the I/O limit */
+ return IoLimit | 0xFFF;
+}
+
+ULONG
+NTAPI
+PciBridgeMemoryBase(IN PPCI_COMMON_HEADER PciData)
+{
+ ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+ /* Return the memory base */
+ return (PciData->u.type1.MemoryBase << 16);
+}
+
+ULONG
+NTAPI
+PciBridgeMemoryLimit(IN PPCI_COMMON_HEADER PciData)
+{
+ ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+ /* Return the memory limit */
+ return (PciData->u.type1.MemoryLimit << 16) | 0xFFFFF;
+}
+
+PHYSICAL_ADDRESS
+NTAPI
+PciBridgePrefetchMemoryBase(IN PPCI_COMMON_HEADER PciData)
+{
+ BOOLEAN Is64Bit;
+ LARGE_INTEGER Base;
+ USHORT PrefetchBase;
+ ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+ /* Get the base */
+ PrefetchBase = PciData->u.type1.PrefetchBase;
+
+ /* Low bit specifies 64-bit address, top bits specify the base */
+ Is64Bit = (PrefetchBase & 0xF) == 1;
+ Base.LowPart = ((PrefetchBase & 0xFFF0) << 16);
+
+ /* Is it 64-bit? */
+ if (Is64Bit)
+ {
+ /* Read the upper 32-bits from the other register */
+ Base.HighPart = PciData->u.type1.PrefetchBaseUpper32;
+ }
+
+ /* Return the base */
+ return Base;
+}
+
+PHYSICAL_ADDRESS
+NTAPI
+PciBridgePrefetchMemoryLimit(IN PPCI_COMMON_HEADER PciData)
+{
+ BOOLEAN Is64Bit;
+ LARGE_INTEGER Limit;
+ USHORT PrefetchLimit;
+ ASSERT(PCI_CONFIGURATION_TYPE(PciData) == PCI_BRIDGE_TYPE);
+
+ /* Get the base */
+ PrefetchLimit = PciData->u.type1.PrefetchLimit;
+
+ /* Low bit specifies 64-bit address, top bits specify the limit */
+ Is64Bit = (PrefetchLimit & 0xF) == 1;
+ Limit.LowPart = (PrefetchLimit << 16) | 0xFFFFF;
+
+ /* Is it 64-bit? */
+ if (Is64Bit)
+ {
+ /* Read the upper 32-bits from the other register */
+ Limit.HighPart = PciData->u.type1.PrefetchLimitUpper32;
+ }
+
+ /* Return the limit */
+ return Limit;
+}
+
+ULONG
+NTAPI
+PciBridgeMemoryWorstCaseAlignment(IN ULONG Length)
+{
+ ULONG Alignment;
+ ASSERT(Length != 0);
+
+ /* Start with highest alignment (2^31) */
+ Alignment = 0x80000000;
+
+ /* Keep dividing until we reach the correct power of two */
+ while (!(Length & Alignment)) Alignment >>= 1;
+
+ /* Return the alignment */
+ return Alignment;
+}
+
+BOOLEAN
+NTAPI
+PciBridgeIsPositiveDecode(IN PPCI_PDO_EXTENSION PdoExtension)
+{
+ /* Undocumented ACPI Method PDEC to get positive decode settings */
+ return PciIsSlotPresentInParentMethod(PdoExtension, 'CEDP');
+}
+
+BOOLEAN
+NTAPI
+PciBridgeIsSubtractiveDecode(IN PPCI_CONFIGURATOR_CONTEXT Context)
+{
+ PPCI_COMMON_HEADER Current, PciData;
+ PPCI_PDO_EXTENSION PdoExtension;
+
+ /* Get pointers from context */
+ Current = Context->Current;
+ PciData = Context->PciData;
+ PdoExtension = Context->PdoExtension;
+
+ /* Only valid for PCI-to-PCI bridges */
+ ASSERT((Current->BaseClass == PCI_CLASS_BRIDGE_DEV) &&
+ (Current->SubClass == PCI_SUBCLASS_BR_PCI_TO_PCI));
+
+ /* Check for hacks first, then check the ProgIf of the bridge */
+ if (!(PdoExtension->HackFlags & PCI_HACK_SUBTRACTIVE_DECODE) &&
+ (Current->ProgIf != 1) &&
+ ((PciData->u.type1.IOLimit & 0xF0) == 0xF0))
+ {
+ /* A subtractive decode bridge would have a ProgIf 1, and no I/O limit */
+ DPRINT("Subtractive decode does not seem to be enabled\n");
+ return FALSE;
+ }
+
+ /*
+ * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
+ * i820, i840, i845 Chipsets) that have subtractive decode broken.
+ */
+ if (((PdoExtension->VendorId == 0x8086) &&
+ ((PdoExtension->DeviceId == 0x2418) ||
+ (PdoExtension->DeviceId == 0x2428) ||
+ (PdoExtension->DeviceId == 0x244E) ||
+ (PdoExtension->DeviceId == 0x2448))) ||
+ (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
+ {
+ /* Check if the ACPI BIOS says positive decode should be enabled */
+ if (PciBridgeIsPositiveDecode(PdoExtension))
+ {
+ /* Obey ACPI */
+ DPRINT1("Putting bridge in positive decode because of PDEC\n");
+ return FALSE;
+ }
+ }
+
+ /* If we found subtractive decode, we'll need a resource update later */
+ DPRINT1("PCI : Subtractive decode on 0x%x\n",
Current->u.type1.SecondaryBus);
+ PdoExtension->UpdateHardware = TRUE;
+ return TRUE;
+}
+
VOID
NTAPI
PPBridge_SaveCurrentSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ NTSTATUS Status;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ PIO_RESOURCE_DESCRIPTOR IoDescriptor;
+ PPCI_FUNCTION_RESOURCES Resources;
+ PCI_COMMON_HEADER BiosData;
+ PPCI_COMMON_HEADER Current;
+ PPCI_COMMON_CONFIG SavedConfig;
+ ULONG i, Bar, BarMask;
+ PULONG BarArray;
+ PHYSICAL_ADDRESS Limit, Base, Length;
+ BOOLEAN HaveIoLimit, CheckAlignment;
+ PPCI_PDO_EXTENSION PdoExtension;
+
+ /* Get the pointers from the extension */
+ PdoExtension = Context->PdoExtension;
+ Resources = PdoExtension->Resources;
+ Current = Context->Current;
+
+ /* Check if decodes are disabled */
+ if (!(Context->Command & (PCI_ENABLE_IO_SPACE | PCI_ENABLE_MEMORY_SPACE)))
+ {
+ /* Well, we're going to need them from somewhere, use the registry data */
+ Status = PciGetBiosConfig(PdoExtension, &BiosData);
+ if (NT_SUCCESS(Status)) Current = &BiosData;
+ }
+
+ /* Scan all current and limit descriptors for each BAR needed */
+ BarArray = Current->u.type1.BaseAddresses;
+ for (i = 0; i < 6; i++)
+ {
+ /* Get the current resource descriptor, and the limit requirement */
+ CmDescriptor = &Resources->Current[i];
+ IoDescriptor = &Resources->Limit[i];
+
+ /* Copy descriptor data, skipping null descriptors */
+ CmDescriptor->Type = IoDescriptor->Type;
+ if (CmDescriptor->Type == CmResourceTypeNull) continue;
+ CmDescriptor->Flags = IoDescriptor->Flags;
+ CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
+
+ /* Initialize the high-parts to zero, since most stuff is 32-bit only */
+ Base.QuadPart = Limit.QuadPart = Length.QuadPart = 0;
+
+ /* Check if we're handling PCI BARs, or the ROM BAR */
+ if ((i < PCI_TYPE1_ADDRESSES) || (i == 5))
+ {
+ /* Is this the ROM BAR? */
+ if (i == 5)
+ {
+ /* Read the correct bar, with the appropriate mask */
+ Bar = Current->u.type1.ROMBaseAddress;
+ BarMask = PCI_ADDRESS_ROM_ADDRESS_MASK;
+
+ /* Decode the base address, and write down the length */
+ Base.LowPart = Bar & BarMask;
+ DPRINT1("ROM BAR Base: %lx\n", Base.LowPart);
+ CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
+ }
+ else
+ {
+ /* Otherwise, get the BAR from the array */
+ Bar = BarArray[i];
+
+ /* Is this an I/O BAR? */
+ if (Bar & PCI_ADDRESS_IO_SPACE)
+ {
+ /* Set the correct mask */
+ ASSERT(CmDescriptor->Type == CmResourceTypePort);
+ BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
+ }
+ else
+ {
+ /* This is a memory BAR, set the correct base */
+ ASSERT(CmDescriptor->Type == CmResourceTypeMemory);
+ BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
+
+ /* IS this a 64-bit BAR? */
+ if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+ {
+ /* Read the next 32-bits as well, ie, the next BAR */
+ Base.HighPart = BarArray[i + 1];
+ }
+ }
+
+ /* Decode the base address, and write down the length */
+ Base.LowPart = Bar & BarMask;
+ DPRINT1("BAR Base: %lx\n", Base.LowPart);
+ CmDescriptor->u.Generic.Length = IoDescriptor->u.Generic.Length;
+ }
+ }
+ else
+ {
+ /* Reset loop conditions */
+ HaveIoLimit = FALSE;
+ CheckAlignment = FALSE;
+
+ /* Check which descriptor is being parsed */
+ if (i == 2)
+ {
+ /* I/O Port Requirements */
+ Base.LowPart = PciBridgeIoBase(Current);
+ Limit.LowPart = PciBridgeIoLimit(Current);
+ DPRINT1("Bridge I/O Base and Limit: %lx %lx\n",
+ Base.LowPart, Limit.LowPart);
+
+ /* Do we have any I/O Port data? */
+ if (!(Base.LowPart) && (Current->u.type1.IOLimit))
+ {
+ /* There's a limit */
+ HaveIoLimit = TRUE;
+ }
+ }
+ else if (i == 3)
+ {
+ /* Memory requirements */
+ Base.LowPart = PciBridgeMemoryBase(Current);
+ Limit.LowPart = PciBridgeMemoryLimit(Current);
+
+ /* These should always be there, so check their alignment */
+ DPRINT1("Bridge MEM Base and Limit: %lx %lx\n",
+ Base.LowPart, Limit.LowPart);
+ CheckAlignment = TRUE;
+ }
+ else if (i == 4)
+ {
+ /* This should only be present for prefetch memory */
+ ASSERT(CmDescriptor->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE);
+ Base = PciBridgePrefetchMemoryBase(Current);
+ Limit = PciBridgePrefetchMemoryLimit(Current);
+
+ /* If it's there, check the alignment */
+ DPRINT1("Bridge Prefetch MEM Base and Limit: %I64x %I64x\n",
Base, Limit);
+ CheckAlignment = TRUE;
+ }
+
+ /* Check for invalid base address */
+ if (Base.QuadPart >= Limit.QuadPart)
+ {
+ /* Assume the descriptor is bogus */
+ CmDescriptor->Type = CmResourceTypeNull;
+ IoDescriptor->Type = CmResourceTypeNull;
+ continue;
+ }
+
+ /* Check if there's no memory, and no I/O port either */
+ if (!(Base.LowPart) && !(HaveIoLimit))
+ {
+ /* This seems like a bogus requirement, ignore it */
+ CmDescriptor->Type = CmResourceTypeNull;
+ continue;
+ }
+
+ /* Set the length to be the limit - the base; should always be 32-bit */
+ Length.QuadPart = Limit.LowPart - Base.LowPart + 1;
+ ASSERT(Length.HighPart == 0);
+ CmDescriptor->u.Generic.Length = Length.LowPart;
+
+ /* Check if alignment should be set */
+ if (CheckAlignment)
+ {
+ /* Compute the required alignment for this length */
+ ASSERT(CmDescriptor->u.Memory.Length > 0);
+ IoDescriptor->u.Memory.Alignment =
+ PciBridgeMemoryWorstCaseAlignment(CmDescriptor->u.Memory.Length);
+ }
+ }
+
+ /* Now set the base address */
+ CmDescriptor->u.Generic.Start.LowPart = Base.LowPart;
+ }
+
+ /* Save PCI settings into the PDO extension for easy access later */
+ PdoExtension->Dependent.type1.PrimaryBus = Current->u.type1.PrimaryBus;
+ PdoExtension->Dependent.type1.SecondaryBus = Current->u.type1.SecondaryBus;
+ PdoExtension->Dependent.type1.SubordinateBus =
Current->u.type1.SubordinateBus;
+
+ /* Check for subtractive decode bridges */
+ if (PdoExtension->Dependent.type1.SubtractiveDecode)
+ {
+ /* Check if legacy VGA decodes are enabled */
+ DPRINT1("Subtractive decode bridge\n");
+ if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+ {
+ /* Save this setting for later */
+ DPRINT1("VGA Bridge\n");
+ PdoExtension->Dependent.type1.VgaBitSet = TRUE;
+ }
+
+ /* Legacy ISA decoding is not compatible with subtractive decode */
+ ASSERT(PdoExtension->Dependent.type1.IsaBitSet == FALSE);
+ }
+ else
+ {
+ /* Check if legacy VGA decodes are enabled */
+ if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+ {
+ /* Save this setting for later */
+ DPRINT1("VGA Bridge\n");
+ PdoExtension->Dependent.type1.VgaBitSet = TRUE;
+
+ /* And on positive decode, we'll also need extra resources locked */
+ PdoExtension->AdditionalResourceCount = 4;
+ }
+
+ /* Check if legacy ISA decoding is enabled */
+ if (Current->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_ISA)
+ {
+ /* Save this setting for later */
+ DPRINT1("ISA Bridge\n");
+ PdoExtension->Dependent.type1.IsaBitSet = TRUE;
+ }
+ }
+
+ /*
+ * Check for Intel ICH PCI-to-PCI (i82801) bridges (used on the i810,
+ * i820, i840, i845 Chipsets) that have subtractive decode broken.
+ */
+ if (((PdoExtension->VendorId == 0x8086) &&
+ ((PdoExtension->DeviceId == 0x2418) ||
+ (PdoExtension->DeviceId == 0x2428) ||
+ (PdoExtension->DeviceId == 0x244E) ||
+ (PdoExtension->DeviceId == 0x2448))) ||
+ (PdoExtension->HackFlags & PCI_HACK_BROKEN_SUBTRACTIVE_DECODE))
+ {
+ /* Check if subtractive decode is actually enabled */
+ if (PdoExtension->Dependent.type1.SubtractiveDecode)
+ {
+ /* We're going to need a copy of the configuration for later use */
+ DPRINT1("apply config save hack to ICH subtractive decode\n");
+ SavedConfig = ExAllocatePoolWithTag(0, PCI_COMMON_HDR_LENGTH,
'PciP');
+ PdoExtension->ParentFdoExtension->PreservedConfig = SavedConfig;
+ if (SavedConfig) RtlCopyMemory(SavedConfig, Current, PCI_COMMON_HDR_LENGTH);
+ }
+ }
}
VOID
NTAPI
PPBridge_SaveLimits(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ PIO_RESOURCE_DESCRIPTOR Limit;
+ PULONG BarArray;
+ PHYSICAL_ADDRESS MemoryLimit;
+ ULONG i;
+ PPCI_COMMON_HEADER Working;
+ PPCI_PDO_EXTENSION PdoExtension;
+
+ /* Get the pointers from the context */
+ Working = Context->PciData;
+ PdoExtension = Context->PdoExtension;
+
+ /* Scan the BARs into the limit descriptors */
+ BarArray = Working->u.type1.BaseAddresses;
+ Limit = PdoExtension->Resources->Limit;
+
+ /* First of all, loop all the BARs */
+ for (i = 0; i < PCI_TYPE1_ADDRESSES; i++)
+ {
+ /* Create a descriptor for their limits */
+ if (PciCreateIoDescriptorFromBarLimit(&Limit[i], &BarArray[i], FALSE))
+ {
+ /* This was a 64-bit descriptor, make sure there's space */
+ ASSERT((i + 1) < PCI_TYPE1_ADDRESSES);
+
+ /* Skip the next descriptor since this one is double sized */
+ i++;
+ (&Limit[i])->Type == CmResourceTypeNull;
+ }
+ }
+
+ /* Check if this is a subtractive decode bridge */
+ if (PciBridgeIsSubtractiveDecode(Context))
+ {
+ /* This bridge is subtractive */
+ PdoExtension->Dependent.type1.SubtractiveDecode = TRUE;
+
+ /* Subtractive bridges cannot use legacy ISA or VGA functionality */
+ PdoExtension->Dependent.type1.IsaBitSet = FALSE;
+ PdoExtension->Dependent.type1.VgaBitSet = FALSE;
+ }
+
+ /* For normal decode bridges, we'll need to find the bridge limits too */
+ if (!PdoExtension->Dependent.type1.SubtractiveDecode)
+ {
+ /* Loop the descriptors that are left, to store the bridge limits */
+ for (i = PCI_TYPE1_ADDRESSES; i < 5; i++)
+ {
+ /* No 64-bit memory addresses, and set the address to 0 to begin */
+ MemoryLimit.HighPart = 0;
+ (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0;
+
+ /* Are we getting the I/O limit? */
+ if (i == 2)
+ {
+ /* There should be one, get it */
+ ASSERT(Working->u.type1.IOLimit != 0);
+ ASSERT((Working->u.type1.IOLimit & 0x0E) == 0);
+ MemoryLimit.LowPart = PciBridgeIoLimit(Working);
+
+ /* Build a descriptor for this limit */
+ (&Limit[i])->Type = CmResourceTypePort;
+ (&Limit[i])->Flags = CM_RESOURCE_PORT_WINDOW_DECODE |
+ CM_RESOURCE_PORT_POSITIVE_DECODE;
+ (&Limit[i])->u.Port.Alignment = 0x1000;
+ (&Limit[i])->u.Port.MinimumAddress.QuadPart = 0;
+ (&Limit[i])->u.Port.MaximumAddress = MemoryLimit;
+ (&Limit[i])->u.Port.Length = 0;
+ }
+ else if (i == 3)
+ {
+ /* There should be a valid memory limit, get it */
+ ASSERT((Working->u.type1.MemoryLimit & 0xF) == 0);
+ MemoryLimit.LowPart = PciBridgeMemoryLimit(Working);
+
+ /* Build the descriptor for it */
+ (&Limit[i])->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ (&Limit[i])->Type = CmResourceTypeMemory;
+ (&Limit[i])->u.Memory.Alignment = 0x100000;
+ (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0;
+ (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit;
+ (&Limit[i])->u.Memory.Length = 0;
+ }
+ else if (Working->u.type1.PrefetchLimit)
+ {
+ /* Get the prefetch memory limit, if there is one */
+ MemoryLimit = PciBridgePrefetchMemoryLimit(Working);
+
+ /* Write out the descriptor for it */
+ (&Limit[i])->Flags = CM_RESOURCE_MEMORY_PREFETCHABLE;
+ (&Limit[i])->Type = CmResourceTypeMemory;
+ (&Limit[i])->u.Memory.Alignment = 0x100000;
+ (&Limit[i])->u.Memory.MinimumAddress.QuadPart = 0;
+ (&Limit[i])->u.Memory.MaximumAddress = MemoryLimit;
+ (&Limit[i])->u.Memory.Length = 0;
+ }
+ else
+ {
+ /* Blank descriptor */
+ (&Limit[i])->Type = CmResourceTypeNull;
+ }
+ }
+ }
+
+ /* Does the ROM have its own BAR? */
+ if (Working->u.type1.ROMBaseAddress & PCI_ROMADDRESS_ENABLED)
+ {
+ /* Build a limit for it as well */
+ PciCreateIoDescriptorFromBarLimit(&Limit[i],
+ &Working->u.type1.ROMBaseAddress,
+ TRUE);
+ }
}
VOID
NTAPI
PPBridge_MassageHeaderForLimitsDetermination(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ PPCI_COMMON_HEADER PciData, Current;
+
+ /* Get pointers from context */
+ PciData = Context->PciData;
+ Current = Context->Current;
+
+ /*
+ * Write FFh everywhere so that the PCI bridge ignores what it can't handle.
+ * Based on the bits that were ignored (still 0), this is how we can tell
+ * what the limit is.
+ */
+ RtlFillMemory(PciData->u.type1.BaseAddresses,
+ FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr) -
+ FIELD_OFFSET(PCI_COMMON_HEADER, u.type1.BaseAddresses),
+ 0xFF);
+
+ /* Copy the saved settings from the current context into the PCI header */
+ PciData->u.type1.PrimaryBus = Current->u.type1.PrimaryBus;
+ PciData->u.type1.SecondaryBus = Current->u.type1.SecondaryBus;
+ PciData->u.type1.SubordinateBus = Current->u.type1.SubordinateBus;
+ PciData->u.type1.SecondaryLatency = Current->u.type1.SecondaryLatency;
+
+ /* No I/O limit or base. The bottom base bit specifies that FIXME */
+ PciData->u.type1.IOBaseUpper16 = 0xFFFE;
+ PciData->u.type1.IOLimitUpper16 = 0xFFFF;
+
+ /* Save secondary status before it gets cleared */
+ Context->SecondaryStatus = Current->u.type1.SecondaryStatus;
+
+ /* Clear secondary status */
+ Current->u.type1.SecondaryStatus = 0;
+ PciData->u.type1.SecondaryStatus = 0;
}
VOID
NTAPI
PPBridge_RestoreCurrent(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
- UNIMPLEMENTED;
- while (TRUE);
+ /* Copy back the secondary status register */
+ Context->Current->u.type1.SecondaryStatus = Context->SecondaryStatus;
}
VOID
@@ -54,24 +630,56 @@
IN PPCI_COMMON_HEADER PciData,
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor)
{
+ /* Does this bridge have VGA decodes on it? */
+ if (PciData->u.type1.BridgeControl & PCI_ENABLE_BRIDGE_VGA)
+ {
+ /* Build a private descriptor with 3 entries */
+ IoDescriptor->Type = CmResourceTypeDevicePrivate;
+ IoDescriptor->u.DevicePrivate.Data[0] = 3;
+ IoDescriptor->u.DevicePrivate.Data[1] = 3;
+
+ /* First, the VGA range at 0xA0000 */
+ IoDescriptor[1].Type = CmResourceTypeMemory;
+ IoDescriptor[1].Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ IoDescriptor[1].u.Port.Length = 0x20000;
+ IoDescriptor[1].u.Port.Alignment = 1;
+ IoDescriptor[1].u.Port.MinimumAddress.QuadPart = 0xA0000;
+ IoDescriptor[1].u.Port.MaximumAddress.QuadPart = 0xBFFFF;
+
+ /* Then, the VGA registers at 0x3B0 */
+ IoDescriptor[2].Type = CmResourceTypePort;
+ IoDescriptor[2].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE |
+ CM_RESOURCE_PORT_10_BIT_DECODE;
+ IoDescriptor[2].u.Port.Length = 12;
+ IoDescriptor[2].u.Port.Alignment = 1;
+ IoDescriptor[2].u.Port.MinimumAddress.QuadPart = 0x3B0;
+ IoDescriptor[2].u.Port.MaximumAddress.QuadPart = 0x3BB;
+
+ /* And finally the VGA registers at 0x3C0 */
+ IoDescriptor[3].Type = CmResourceTypePort;
+ IoDescriptor[3].Flags = CM_RESOURCE_PORT_POSITIVE_DECODE |
+ CM_RESOURCE_PORT_10_BIT_DECODE;
+ IoDescriptor[3].u.Port.Length = 32;
+ IoDescriptor[3].u.Port.Alignment = 1;
+ IoDescriptor[3].u.Port.MinimumAddress.QuadPart = 0x3C0;
+ IoDescriptor[3].u.Port.MaximumAddress.QuadPart = 0x3DF;
+ }
+}
+
+VOID
+NTAPI
+PPBridge_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context)
+{
UNIMPLEMENTED;
while (TRUE);
}
VOID
NTAPI
-PPBridge_ResetDevice(IN PPCI_CONFIGURATOR_CONTEXT Context)
+PPBridge_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
{
UNIMPLEMENTED;
while (TRUE);
}
-VOID
-NTAPI
-PPBridge_ChangeResourceSettings(IN PPCI_CONFIGURATOR_CONTEXT Context)
-{
- UNIMPLEMENTED;
- while (TRUE);
-}
-
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?r…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Tue Jul 27 03:24:24 2010
@@ -1130,6 +1130,115 @@
return FoundSlot;
}
+ULONG
+NTAPI
+PciGetLengthFromBar(IN ULONG Bar)
+{
+ ULONG Length;
+
+ /* I/O addresses vs. memory addresses start differently due to alignment */
+ Length = 1 << ((Bar & PCI_ADDRESS_IO_SPACE) ? 2 : 4);
+
+ /* Keep going until a set bit */
+ while (!(Length & Bar) && (Length)) Length <<= 1;
+
+ /* Return the length (might be 0 on 64-bit because it's the low-word) */
+ if ((Bar & PCI_ADDRESS_MEMORY_TYPE_MASK) != PCI_TYPE_64BIT) ASSERT(Length);
+ return Length;
+}
+
+BOOLEAN
+NTAPI
+PciCreateIoDescriptorFromBarLimit(PIO_RESOURCE_DESCRIPTOR ResourceDescriptor,
+ IN PULONG BarArray,
+ IN BOOLEAN Rom)
+{
+ ULONG CurrentBar, BarLength, BarMask;
+ BOOLEAN Is64BitBar = FALSE;
+
+ /* Check if the BAR is nor I/O nor memory */
+ CurrentBar = BarArray[0];
+ if (!(CurrentBar & ~PCI_ADDRESS_IO_SPACE))
+ {
+ /* Fail this descriptor */
+ ResourceDescriptor->Type = CmResourceTypeNull;
+ return FALSE;
+ }
+
+ /* Set default flag and clear high words */
+ ResourceDescriptor->Flags = 0;
+ ResourceDescriptor->u.Generic.MaximumAddress.HighPart = 0;
+ ResourceDescriptor->u.Generic.MinimumAddress.LowPart = 0;
+ ResourceDescriptor->u.Generic.MinimumAddress.HighPart = 0;
+
+ /* Check for ROM Address */
+ if (Rom)
+ {
+ /* Clean up the BAR to get just the address */
+ CurrentBar &= PCI_ADDRESS_ROM_ADDRESS_MASK;
+ if (!CurrentBar)
+ {
+ /* Invalid ar, fail this descriptor */
+ ResourceDescriptor->Type = CmResourceTypeNull;
+ return FALSE;
+ }
+
+ /* ROM Addresses are always read only */
+ ResourceDescriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ /* Compute the length, assume it's the alignment for now */
+ BarLength = PciGetLengthFromBar(CurrentBar);
+ ResourceDescriptor->u.Generic.Length = BarLength;
+ ResourceDescriptor->u.Generic.Alignment = BarLength;
+
+ /* Check what kind of BAR this is */
+ if (CurrentBar & PCI_ADDRESS_IO_SPACE)
+ {
+ /* Use correct mask to decode the address */
+ BarMask = PCI_ADDRESS_IO_ADDRESS_MASK;
+
+ /* Set this as an I/O Port descriptor */
+ ResourceDescriptor->Type = CmResourceTypePort;
+ ResourceDescriptor->Flags = CM_RESOURCE_PORT_IO;
+ }
+ else
+ {
+ /* Use correct mask to decode the address */
+ BarMask = PCI_ADDRESS_MEMORY_ADDRESS_MASK;
+
+ /* Set this as a memory descriptor */
+ ResourceDescriptor->Type = CmResourceTypeMemory;
+
+ /* Check if it's 64-bit or 20-bit decode */
+ if ((CurrentBar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_64BIT)
+ {
+ /* The next BAR has the high word, read it */
+ ResourceDescriptor->u.Port.MaximumAddress.HighPart = BarArray[1];
+ Is64BitBar = TRUE;
+ }
+ else if ((CurrentBar & PCI_ADDRESS_MEMORY_TYPE_MASK) == PCI_TYPE_20BIT)
+ {
+ /* Use the correct mask to decode the address */
+ BarMask = ~0xFFF0000F;
+ }
+
+ /* Check if the BAR is listed as prefetchable memory */
+ if (CurrentBar & PCI_ADDRESS_MEMORY_PREFETCHABLE)
+ {
+ /* Mark the descriptor in the same way */
+ ResourceDescriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+ }
+
+ /* Now write down the maximum address based on the base + length */
+ ResourceDescriptor->u.Port.MaximumAddress.QuadPart = (CurrentBar & BarMask) +
+ BarLength - 1;
+
+ /* Return if this is a 64-bit BAR, so the loop code knows to skip the next one */
+ return Is64BitBar;
+}
+
VOID
NTAPI
PciDecodeEnable(IN PPCI_PDO_EXTENSION PdoExtension,